Compare commits

..

1 Commits

Author SHA1 Message Date
Zachary Yedidia
6f302826c8 Add bracket surround 2017-09-13 10:48:53 -04:00
5 changed files with 127 additions and 99 deletions

View File

@@ -62,71 +62,54 @@ func (v *View) MousePress(usePlugin bool, e *tcell.EventMouse) bool {
return false return false
} }
rawX, rawY := e.Position() x, y := e.Position()
x -= v.lineNumOffset - v.leftCol + v.x
x := rawX - v.lineNumOffset - v.leftCol + v.x y += v.Topline - v.y
y := rawY + v.Topline - v.y
// This is usually bound to left click // This is usually bound to left click
if !(rawX == v.x+v.Width || rawY == v.y+v.Height || v.resizeX || v.resizeY) { v.MoveToMouseClick(x, y)
v.MoveToMouseClick(x, y)
}
if v.mouseReleased { if v.mouseReleased {
if rawX == v.x+v.Width { if len(v.Buf.cursors) > 1 {
v.resizeX = true for i := 1; i < len(v.Buf.cursors); i++ {
} else if rawY == v.y+v.Height { v.Buf.cursors[i] = nil
v.resizeY = true
} else {
if len(v.Buf.cursors) > 1 {
for i := 1; i < len(v.Buf.cursors); i++ {
v.Buf.cursors[i] = nil
}
v.Buf.cursors = v.Buf.cursors[:1]
v.Buf.UpdateCursors()
v.Cursor.ResetSelection()
v.Relocate()
} }
if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold { v.Buf.cursors = v.Buf.cursors[:1]
if v.doubleClick { v.Buf.UpdateCursors()
// Triple click v.Cursor.ResetSelection()
v.lastClickTime = time.Now() v.Relocate()
}
v.tripleClick = true if time.Since(v.lastClickTime)/time.Millisecond < doubleClickThreshold {
v.doubleClick = false if v.doubleClick {
// Triple click
v.Cursor.SelectLine()
v.Cursor.CopySelection("primary")
} else {
// Double click
v.lastClickTime = time.Now()
v.doubleClick = true
v.tripleClick = false
v.Cursor.SelectWord()
v.Cursor.CopySelection("primary")
}
} else {
v.doubleClick = false
v.tripleClick = false
v.lastClickTime = time.Now() v.lastClickTime = time.Now()
v.Cursor.OrigSelection[0] = v.Cursor.Loc v.tripleClick = true
v.Cursor.CurSelection[0] = v.Cursor.Loc v.doubleClick = false
v.Cursor.CurSelection[1] = v.Cursor.Loc
v.Cursor.SelectLine()
v.Cursor.CopySelection("primary")
} else {
// Double click
v.lastClickTime = time.Now()
v.doubleClick = true
v.tripleClick = false
v.Cursor.SelectWord()
v.Cursor.CopySelection("primary")
} }
} else {
v.doubleClick = false
v.tripleClick = false
v.lastClickTime = time.Now()
v.Cursor.OrigSelection[0] = v.Cursor.Loc
v.Cursor.CurSelection[0] = v.Cursor.Loc
v.Cursor.CurSelection[1] = v.Cursor.Loc
} }
v.mouseReleased = false v.mouseReleased = false
} else if !v.mouseReleased { } else if !v.mouseReleased {
if v.resizeX { if v.tripleClick {
v.Width = rawX - v.x
v.LockWidth = true
v.splitNode.parent.ResizeSplits()
} else if v.resizeY {
v.Height = rawY - v.y
v.LockHeight = true
v.splitNode.parent.ResizeSplits()
} else if v.tripleClick {
v.Cursor.AddLineToSelection() v.Cursor.AddLineToSelection()
} else if v.doubleClick { } else if v.doubleClick {
v.Cursor.AddWordToSelection() v.Cursor.AddWordToSelection()
@@ -1869,6 +1852,68 @@ func (v *View) PreviousSplit(usePlugin bool) bool {
return false return false
} }
func (v *View) WrapBracket(usePlugin bool) bool {
if v.Cursor.HasSelection() {
lockPollEvent = true
event := screen.PollEvent()
lockPollEvent = false
ev, ok := event.(*tcell.EventKey)
if !ok {
return false
}
if !strings.Contains("()[]{}\"'", string(ev.Rune())) {
return false
}
start := v.Cursor.CurSelection[0]
end := v.Cursor.CurSelection[1]
if start.Y != end.Y {
return false
}
close := map[string]string{
")": ")",
"]": "]",
"}": "}",
"(": ")",
"[": "]",
"{": "}",
"\"": "\"",
"'": "'",
}
open := map[string]string{
")": "(",
"]": "[",
"}": "{",
"(": "(",
"[": "[",
"{": "{",
"\"": "\"",
"'": "'",
}
if usePlugin && !PreActionCall("WrapBracket", v) {
return false
}
r := string(ev.Rune())
if start.GreaterThan(end) {
start, end = end, start
v.Buf.Insert(start, open[r])
v.Buf.Insert(end.Move(1, v.Buf), close[r])
v.Cursor.CurSelection[1] = start
} else {
v.Buf.Insert(start, open[r])
v.Buf.Insert(end.Move(1, v.Buf), close[r])
v.Cursor.CurSelection[0] = start
}
if usePlugin {
return PostActionCall("WrapBracket", v)
}
}
return false
}
var curMacro []interface{} var curMacro []interface{}
var recordingMacro bool var recordingMacro bool

View File

@@ -69,6 +69,7 @@ var bindingActions = map[string]func(*View, bool) bool{
"PastePrimary": (*View).PastePrimary, "PastePrimary": (*View).PastePrimary,
"SelectAll": (*View).SelectAll, "SelectAll": (*View).SelectAll,
"OpenFile": (*View).OpenFile, "OpenFile": (*View).OpenFile,
"WrapBracket": (*View).WrapBracket,
"Start": (*View).Start, "Start": (*View).Start,
"End": (*View).End, "End": (*View).End,
"PageUp": (*View).PageUp, "PageUp": (*View).PageUp,
@@ -438,6 +439,7 @@ func DefaultBindings() map[string]string {
"Down": "CursorDown", "Down": "CursorDown",
"Right": "CursorRight", "Right": "CursorRight",
"Left": "CursorLeft", "Left": "CursorLeft",
"Alt-j": "WrapBracket",
"ShiftUp": "SelectUp", "ShiftUp": "SelectUp",
"ShiftDown": "SelectDown", "ShiftDown": "SelectDown",
"ShiftLeft": "SelectLeft", "ShiftLeft": "SelectLeft",

View File

@@ -112,9 +112,6 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
// We'll either draw the length of the line, or the width of the screen // We'll either draw the length of the line, or the width of the screen
// whichever is smaller // whichever is smaller
lineLength := min(StringWidth(lineStr, tabsize), width) lineLength := min(StringWidth(lineStr, tabsize), width)
if lineLength < 0 {
return
}
c.lines = append(c.lines, make([]*Char, lineLength)) c.lines = append(c.lines, make([]*Char, lineLength))
wrap := false wrap := false
@@ -136,50 +133,38 @@ func (c *CellView) Draw(buf *Buffer, top, height, left, width int) {
char := line[colN] char := line[colN]
if viewCol >= 0 { if viewCol >= 0 {
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, curStyle, 1}
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, char, curStyle, 1}
}
} }
if char == '\t' { if char == '\t' {
charWidth := tabsize - (viewCol+left)%tabsize charWidth := tabsize - (viewCol+left)%tabsize
if viewCol >= 0 { if viewCol >= 0 {
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol].drawChar = indentchar
c.lines[viewLine][viewCol].drawChar = indentchar c.lines[viewLine][viewCol].width = charWidth
c.lines[viewLine][viewCol].width = charWidth
}
indentStyle := curStyle indentStyle := curStyle
if group, ok := colorscheme["indent-char"]; ok { if group, ok := colorscheme["indent-char"]; ok {
indentStyle = group indentStyle = group
} }
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol].style = indentStyle
c.lines[viewLine][viewCol].style = indentStyle
}
} }
for i := 1; i < charWidth; i++ { for i := 1; i < charWidth; i++ {
viewCol++ viewCol++
if viewCol >= 0 && viewCol < lineLength { if viewCol >= 0 && viewCol < lineLength {
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
}
} }
} }
viewCol++ viewCol++
} else if runewidth.RuneWidth(char) > 1 { } else if runewidth.RuneWidth(char) > 1 {
charWidth := runewidth.RuneWidth(char) charWidth := runewidth.RuneWidth(char)
if viewCol >= 0 { if viewCol >= 0 {
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol].width = charWidth
c.lines[viewLine][viewCol].width = charWidth
}
} }
for i := 1; i < charWidth; i++ { for i := 1; i < charWidth; i++ {
viewCol++ viewCol++
if viewCol >= 0 && viewCol < lineLength { if viewCol >= 0 && viewCol < lineLength {
if viewCol < len(c.lines[viewLine]) { c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
c.lines[viewLine][viewCol] = &Char{Loc{viewCol, viewLine}, Loc{colN, lineN}, char, ' ', curStyle, 1}
}
} }
} }
viewCol++ viewCol++

View File

@@ -59,6 +59,9 @@ var (
// Event channel // Event channel
events chan tcell.Event events chan tcell.Event
autosave chan bool autosave chan bool
// Read events on another thread or wait for a temporary read
lockPollEvent bool
) )
// LoadInput determines which files should be loaded into buffers // LoadInput determines which files should be loaded into buffers
@@ -419,8 +422,9 @@ func main() {
// Here is the event loop which runs in a separate thread // Here is the event loop which runs in a separate thread
go func() { go func() {
for { for {
if screen != nil { if screen != nil && !lockPollEvent {
events <- screen.PollEvent() events <- screen.PollEvent()
time.Sleep(1 * time.Millisecond)
} }
} }
}() }()
@@ -476,7 +480,7 @@ func main() {
// We loop through each view in the current tab and make sure the current view // We loop through each view in the current tab and make sure the current view
// is the one being clicked in // is the one being clicked in
for _, v := range tabs[curTab].views { for _, v := range tabs[curTab].views {
if x > v.x && x <= v.x+v.Width && y > v.y && y <= v.y+v.Height { if x >= v.x && x < v.x+v.Width && y >= v.y && y < v.y+v.Height {
tabs[curTab].CurView = v.Num tabs[curTab].CurView = v.Num
} }
} }

View File

@@ -91,9 +91,6 @@ type View struct {
cellview *CellView cellview *CellView
splitNode *LeafNode splitNode *LeafNode
resizeX bool
resizeY bool
} }
// NewView returns a new fullscreen view // NewView returns a new fullscreen view
@@ -602,26 +599,21 @@ func (v *View) HandleEvent(event tcell.Event) {
// Mouse event with no click // Mouse event with no click
if !v.mouseReleased { if !v.mouseReleased {
// Mouse was just released // Mouse was just released
if v.resizeX || v.resizeY {
v.resizeX = false
v.resizeY = false
} else {
x, y := e.Position() x, y := e.Position()
x -= v.lineNumOffset - v.leftCol + v.x x -= v.lineNumOffset - v.leftCol + v.x
y += v.Topline - v.y y += v.Topline - v.y
// Relocating here isn't really necessary because the cursor will // Relocating here isn't really necessary because the cursor will
// be in the right place from the last mouse event // be in the right place from the last mouse event
// However, if we are running in a terminal that doesn't support mouse motion // However, if we are running in a terminal that doesn't support mouse motion
// events, this still allows the user to make selections, except only after they // events, this still allows the user to make selections, except only after they
// release the mouse // release the mouse
if !v.doubleClick && !v.tripleClick { if !v.doubleClick && !v.tripleClick {
v.MoveToMouseClick(x, y) v.MoveToMouseClick(x, y)
v.Cursor.SetSelectionEnd(v.Cursor.Loc) v.Cursor.SetSelectionEnd(v.Cursor.Loc)
v.Cursor.CopySelection("primary") v.Cursor.CopySelection("primary")
}
} }
v.mouseReleased = true v.mouseReleased = true
} }