More actions

This commit is contained in:
Zachary Yedidia
2018-08-28 23:30:39 -04:00
parent 7d87e6db99
commit 31fb3f2df2
6 changed files with 103 additions and 6 deletions

View File

@@ -2,8 +2,10 @@ package action
import (
"os"
"unicode/utf8"
"github.com/zyedidia/micro/cmd/micro/screen"
"github.com/zyedidia/micro/cmd/micro/util"
"github.com/zyedidia/tcell"
)
@@ -262,6 +264,11 @@ func (h *BufHandler) SelectToEnd() bool {
// InsertSpace inserts a space
func (h *BufHandler) InsertSpace() bool {
if h.Cursor.HasSelection() {
h.Cursor.DeleteSelection()
h.Cursor.ResetSelection()
}
h.Buf.Insert(h.Cursor.Loc, " ")
return true
}
@@ -272,6 +279,30 @@ func (h *BufHandler) InsertNewline() bool {
// Backspace deletes the previous character
func (h *BufHandler) Backspace() bool {
if h.Cursor.HasSelection() {
h.Cursor.DeleteSelection()
h.Cursor.ResetSelection()
} else if h.Cursor.Loc.GreaterThan(h.Buf.Start()) {
// We have to do something a bit hacky here because we want to
// delete the line by first moving left and then deleting backwards
// but the undo redo would place the cursor in the wrong place
// So instead we move left, save the position, move back, delete
// and restore the position
// If the user is using spaces instead of tabs and they are deleting
// whitespace at the start of the line, we should delete as if it's a
// tab (tabSize number of spaces)
lineStart := util.SliceStart(h.Buf.LineBytes(h.Cursor.Y), h.Cursor.X)
tabSize := int(h.Buf.Settings["tabsize"].(float64))
if h.Buf.Settings["tabstospaces"].(bool) && util.IsSpaces(lineStart) && len(lineStart) != 0 && utf8.RuneCount(lineStart)%tabSize == 0 {
loc := h.Cursor.Loc
h.Buf.Remove(loc.Move(-tabSize, h.Buf), loc)
} else {
loc := h.Cursor.Loc
h.Buf.Remove(loc.Move(-1, h.Buf), loc)
}
}
h.Cursor.LastVisualX = h.Cursor.GetVisualX()
return true
}

View File

@@ -102,21 +102,29 @@ modSearch:
// see if the key is in bindingKeys with the Ctrl prefix.
k = string(unicode.ToUpper(rune(k[0]))) + k[1:]
if code, ok := keyEvents["Ctrl"+k]; ok {
var r tcell.Key
if code < 256 {
r = code
}
// It is, we're done.
return KeyEvent{
code: code,
mod: modifiers,
r: rune(code),
r: rune(r),
}, true
}
}
// See if we can find the key in bindingKeys
if code, ok := keyEvents[k]; ok {
var r tcell.Key
if code < 256 {
r = code
}
return KeyEvent{
code: code,
mod: modifiers,
r: 0,
r: rune(r),
}, true
}

View File

@@ -4,6 +4,7 @@ import (
"time"
"github.com/zyedidia/micro/cmd/micro/buffer"
"github.com/zyedidia/micro/cmd/micro/util"
"github.com/zyedidia/tcell"
)
@@ -19,10 +20,23 @@ func init() {
}
func BufMapKey(k KeyEvent, action string) {
BufKeyBindings[k] = BufKeyActions[action]
if f, ok := BufKeyActions[action]; ok {
BufKeyBindings[k] = f
} else {
util.TermMessage("Error:", action, "does not exist")
}
}
func BufMapMouse(k MouseEvent, action string) {
BufMouseBindings[k] = BufMouseActions[action]
if f, ok := BufMouseActions[action]; ok {
BufMouseBindings[k] = f
} else if f, ok := BufKeyActions[action]; ok {
// allowed to map mouse buttons to key actions
BufMouseBindings[k] = func(h *BufHandler, e *tcell.EventMouse) bool {
return f(h)
}
} else {
util.TermMessage("Error:", action, "does not exist")
}
}
// The BufHandler connects the buffer and the window
@@ -91,7 +105,10 @@ func (h *BufHandler) HandleEvent(event tcell.Event) {
mod: e.Modifiers(),
r: e.Rune(),
}
h.DoKeyEvent(ke)
done := h.DoKeyEvent(ke)
if !done && e.Key() == tcell.KeyRune {
h.DoRuneInsert(e.Rune())
}
case *tcell.EventMouse:
me := MouseEvent{
btn: e.Buttons(),
@@ -117,6 +134,22 @@ func (h *BufHandler) DoMouseEvent(e MouseEvent, te *tcell.EventMouse) bool {
return false
}
func (h *BufHandler) DoRuneInsert(r rune) {
// Insert a character
if h.Cursor.HasSelection() {
h.Cursor.DeleteSelection()
h.Cursor.ResetSelection()
}
if h.isOverwriteMode {
next := h.Cursor.Loc
next.X++
h.Buf.Replace(h.Cursor.Loc, next, string(r))
} else {
h.Buf.Insert(h.Cursor.Loc, string(r))
}
}
var BufKeyActions = map[string]BufKeyAction{
"CursorUp": (*BufHandler).CursorUp,
"CursorDown": (*BufHandler).CursorDown,

View File

@@ -320,6 +320,20 @@ func calcHash(b *Buffer, out *[md5.Size]byte) {
h.Sum((*out)[:0])
}
func (b *Buffer) insert(pos Loc, value []byte) {
b.isModified = true
b.LineArray.insert(pos, value)
}
func (b *Buffer) remove(start, end Loc) []byte {
b.isModified = true
sub := b.LineArray.remove(start, end)
return sub
}
func (b *Buffer) deleteToEnd(start Loc) {
b.isModified = true
b.LineArray.deleteToEnd(start)
}
// UpdateRules updates the syntax rules and filetype for this buffer
// This is called when the colorscheme changes
func (b *Buffer) UpdateRules() {

View File

@@ -24,7 +24,7 @@ func Unlock() {
var screenWasNil bool
func TempFini() {
screenWasNil := Screen == nil
screenWasNil = Screen == nil
if !screenWasNil {
Lock()

View File

@@ -139,6 +139,17 @@ func IsWordChar(r rune) bool {
return (r >= '0' && r <= '9') || (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r == '_')
}
// IsSpaces checks if a given string is only spaces
func IsSpaces(str []byte) bool {
for _, c := range str {
if c != ' ' {
return false
}
}
return true
}
// IsWhitespace returns true if the given rune is a space, tab, or newline
func IsWhitespace(c rune) bool {
return c == ' ' || c == '\t' || c == '\n'