Implement searching

This commit is contained in:
Zachary Yedidia
2019-01-03 15:27:43 -05:00
parent f63c72c50d
commit e63a3c8917
10 changed files with 348 additions and 25 deletions

View File

@@ -1,6 +1,7 @@
package action
import (
"log"
"os"
"strings"
"time"
@@ -560,6 +561,37 @@ func (h *BufHandler) SaveAs() bool {
// Find opens a prompt and searches forward for the input
func (h *BufHandler) Find() bool {
InfoBar.Prompt("Find: ", "", func(resp string) {
match, found, _ := h.Buf.FindNext(resp, h.Cursor.Loc, true)
if found {
h.Cursor.SetSelectionStart(match[0])
h.Cursor.SetSelectionEnd(match[1])
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
} else {
log.Println("RESET")
h.Cursor.ResetSelection()
}
}, func(resp string, canceled bool) {
if !canceled {
match, found, err := h.Buf.FindNext(resp, h.Cursor.Loc, true)
if err != nil {
InfoBar.Error(err)
}
if found {
h.Cursor.SetSelectionStart(match[0])
h.Cursor.SetSelectionEnd(match[1])
h.Cursor.OrigSelection[0] = h.Cursor.CurSelection[0]
h.Cursor.OrigSelection[1] = h.Cursor.CurSelection[1]
h.Cursor.Loc = h.Cursor.CurSelection[1]
} else {
h.Cursor.ResetSelection()
}
} else {
h.Cursor.ResetSelection()
}
})
return true
}
@@ -725,7 +757,7 @@ func (h *BufHandler) SelectAll() bool {
// OpenFile opens a new file in the buffer
func (h *BufHandler) OpenFile() bool {
InfoBar.Prompt("> ", "open ", func(resp string, canceled bool) {
InfoBar.Prompt("> ", "open ", nil, func(resp string, canceled bool) {
if !canceled {
HandleCommand(resp)
}
@@ -889,7 +921,7 @@ func (h *BufHandler) ShellMode() bool {
// CommandMode lets the user enter a command
func (h *BufHandler) CommandMode() bool {
InfoBar.Prompt("> ", "", func(resp string, canceled bool) {
InfoBar.Prompt("> ", "", nil, func(resp string, canceled bool) {
if !canceled {
HandleCommand(resp)
}

View File

@@ -103,7 +103,8 @@ modSearch:
k = string(unicode.ToUpper(rune(k[0]))) + k[1:]
if code, ok := keyEvents["Ctrl"+k]; ok {
var r tcell.Key
if code < 256 {
// Special case for escape, for some reason tcell doesn't send it with the esc character
if code < 256 && code != 27 {
r = code
}
// It is, we're done.
@@ -118,7 +119,8 @@ modSearch:
// See if we can find the key in bindingKeys
if code, ok := keyEvents[k]; ok {
var r tcell.Key
if code < 256 {
// Special case for escape, for some reason tcell doesn't send it with the esc character
if code < 256 && code != 27 {
r = code
}
return KeyEvent{

View File

@@ -22,6 +22,7 @@ func init() {
BufMouseBindings = make(map[MouseEvent]BufMouseAction)
}
// BufMapKey maps a key event to an action
func BufMapKey(k KeyEvent, action string) {
if f, ok := BufKeyActions[action]; ok {
BufKeyStrings[k] = action
@@ -30,6 +31,8 @@ func BufMapKey(k KeyEvent, action string) {
util.TermMessage("Error:", action, "does not exist")
}
}
// BufMapMouse maps a mouse event to an action
func BufMapMouse(k MouseEvent, action string) {
if f, ok := BufMouseActions[action]; ok {
BufMouseBindings[k] = f
@@ -147,10 +150,13 @@ func (h *BufHandler) HandleEvent(event tcell.Event) {
}
}
// DoKeyEvent executes a key event by finding the action it is bound
// to and executing it (possibly multiple times for multiple cursors)
func (h *BufHandler) DoKeyEvent(e KeyEvent) bool {
if action, ok := BufKeyBindings[e]; ok {
for _, a := range MultiActions {
if a == BufKeyStrings[e] {
estr := BufKeyStrings[e]
for _, s := range MultiActions {
if s == estr {
cursors := h.Buf.GetCursors()
for _, c := range cursors {
h.Buf.SetCurCursor(c.Num)
@@ -170,6 +176,8 @@ func (h *BufHandler) DoKeyEvent(e KeyEvent) bool {
return false
}
// DoMouseEvent executes a mouse event by finding the action it is bound
// to and executing it
func (h *BufHandler) DoMouseEvent(e MouseEvent, te *tcell.EventMouse) bool {
if action, ok := BufMouseBindings[e]; ok {
if action(h, te) {
@@ -180,6 +188,8 @@ func (h *BufHandler) DoMouseEvent(e MouseEvent, te *tcell.EventMouse) bool {
return false
}
// DoRuneInsert inserts a given rune into the current buffer
// (possibly multiple times for multiple cursors)
func (h *BufHandler) DoRuneInsert(r rune) {
cursors := h.Buf.GetCursors()
for _, c := range cursors {
@@ -199,6 +209,7 @@ func (h *BufHandler) DoRuneInsert(r rune) {
}
}
// BufKeyActions contains the list of all possible key actions the bufhandler could execute
var BufKeyActions = map[string]BufKeyAction{
"CursorUp": (*BufHandler).CursorUp,
"CursorDown": (*BufHandler).CursorDown,
@@ -297,13 +308,13 @@ var BufKeyActions = map[string]BufKeyAction{
// This was changed to InsertNewline but I don't want to break backwards compatibility
"InsertEnter": (*BufHandler).InsertNewline,
}
// BufMouseActions contains the list of all possible mouse actions the bufhandler could execute
var BufMouseActions = map[string]BufMouseAction{
"MousePress": (*BufHandler).MousePress,
"MouseMultiCursor": (*BufHandler).MouseMultiCursor,
}
const funcPrefixLen = 21 // length of "action.(*BufHandler)."
// MultiActions is a list of actions that should be executed multiple
// times if there are multiple cursors (one per cursor)
// Generally actions that modify global editor state like quitting or

View File

@@ -119,7 +119,7 @@ func DefaultCommands() map[string]StrCommand {
// enter
func CommandEditAction(prompt string) BufKeyAction {
return func(h *BufHandler) bool {
InfoBar.Prompt("> ", prompt, func(resp string, canceled bool) {
InfoBar.Prompt("> ", prompt, nil, func(resp string, canceled bool) {
if !canceled {
HandleCommand(resp)
}

View File

@@ -8,12 +8,12 @@ import (
type EditPane struct {
display.Window
Handler
*BufHandler
}
type InfoPane struct {
display.Window
Handler
*InfoHandler
*info.InfoBuf
}
@@ -22,7 +22,7 @@ func NewBufEditPane(x, y, width, height int, b *buffer.Buffer) *EditPane {
// TODO: can probably replace editpane with bufhandler entirely
w := display.NewBufWindow(x, y, width, height, b)
e.Window = w
e.Handler = NewBufHandler(b, w)
e.BufHandler = NewBufHandler(b, w)
return e
}
@@ -32,7 +32,7 @@ func NewInfoBar() *InfoPane {
ib := info.NewBuffer()
w := display.NewInfoWindow(ib)
e.Window = w
e.Handler = NewBufHandler(ib.Buffer, w)
e.InfoHandler = NewInfoHandler(ib, w)
e.InfoBuf = ib
return e

View File

@@ -0,0 +1,158 @@
package action
import (
"strings"
"github.com/zyedidia/micro/cmd/micro/display"
"github.com/zyedidia/micro/cmd/micro/info"
"github.com/zyedidia/tcell"
)
type InfoKeyAction func(*InfoHandler)
type InfoHandler struct {
*BufHandler
*info.InfoBuf
}
func NewInfoHandler(ib *info.InfoBuf, w display.Window) *InfoHandler {
ih := new(InfoHandler)
ih.InfoBuf = ib
ih.BufHandler = NewBufHandler(ib.Buffer, w)
return ih
}
func (h *InfoHandler) HandleEvent(event tcell.Event) {
switch e := event.(type) {
case *tcell.EventKey:
ke := KeyEvent{
code: e.Key(),
mod: e.Modifiers(),
r: e.Rune(),
}
done := h.DoKeyEvent(ke)
if !done && e.Key() == tcell.KeyRune {
h.DoRuneInsert(e.Rune())
}
case *tcell.EventMouse:
h.BufHandler.HandleEvent(event)
}
}
func (h *InfoHandler) DoKeyEvent(e KeyEvent) bool {
done := false
if action, ok := BufKeyBindings[e]; ok {
estr := BufKeyStrings[e]
for _, s := range InfoNones {
if s == estr {
return false
}
}
for s, a := range InfoOverrides {
if s == estr {
done = true
a(h)
break
}
}
if !done {
done = action(h.BufHandler)
}
}
if done && h.EventCallback != nil {
h.EventCallback(strings.TrimSpace(string(h.LineBytes(0))))
}
return done
}
func (h *InfoHandler) DoRuneInsert(r rune) {
h.BufHandler.DoRuneInsert(r)
if h.EventCallback != nil {
h.EventCallback(strings.TrimSpace(string(h.LineBytes(0))))
}
}
// InfoNones is a list of actions that should have no effect when executed
// by an infohandler
var InfoNones = []string{
"Save",
"SaveAll",
"SaveAs",
"Find",
"FindNext",
"FindPrevious",
"Center",
"DuplicateLine",
"MoveLinesUp",
"MoveLinesDown",
"OpenFile",
"Start",
"End",
"PageUp",
"PageDown",
"SelectPageUp",
"SelectPageDown",
"HalfPageUp",
"HalfPageDown",
"ToggleHelp",
"ToggleKeyMenu",
"ToggleRuler",
"JumpLine",
"ClearStatus",
"ShellMode",
"CommandMode",
"AddTab",
"PreviousTab",
"NextTab",
"NextSplit",
"PreviousSplit",
"Unsplit",
"VSplit",
"HSplit",
"ToggleMacro",
"PlayMacro",
"Suspend",
"ScrollUp",
"ScrollDown",
"SpawnMultiCursor",
"SpawnMultiCursorSelect",
"RemoveMultiCursor",
"RemoveAllMultiCursors",
"SkipMultiCursor",
}
// InfoOverrides is the list of actions which have been overriden
// by the infohandler
var InfoOverrides = map[string]InfoKeyAction{
"CursorUp": (*InfoHandler).CursorUp,
"CursorDown": (*InfoHandler).CursorDown,
"InsertNewline": (*InfoHandler).InsertNewline,
"InsertTab": (*InfoHandler).InsertTab,
"Escape": (*InfoHandler).Escape,
"Quit": (*InfoHandler).Quit,
"QuitAll": (*InfoHandler).QuitAll,
}
func (h *InfoHandler) CursorUp() {
// TODO: history
}
func (h *InfoHandler) CursorDown() {
// TODO: history
}
func (h *InfoHandler) InsertTab() {
// TODO: autocomplete
}
func (h *InfoHandler) InsertNewline() {
h.DonePrompt(false)
}
func (h *InfoHandler) Quit() {
h.DonePrompt(true)
}
func (h *InfoHandler) QuitAll() {
h.DonePrompt(true)
}
func (h *InfoHandler) Escape() {
h.DonePrompt(true)
}