Added temporary command x-replace
This runs a search and replace over the entire model. This is just temporary at the moment in order to get something working. Also added hitting backspace on an empty entrybox to cancel it.
This commit is contained in:
parent
04aeff6b52
commit
6e6e586f1d
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/lmika/shellwords"
|
||||||
|
|
||||||
"github.com/lmika/ted/ui"
|
"github.com/lmika/ted/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -60,20 +62,19 @@ func (cm *CommandMapping) KeyMapping(key rune) *Command {
|
||||||
// Evaluate a command
|
// Evaluate a command
|
||||||
func (cm *CommandMapping) Eval(ctx *CommandContext, expr string) error {
|
func (cm *CommandMapping) Eval(ctx *CommandContext, expr string) error {
|
||||||
// TODO: Use propper expression language here
|
// TODO: Use propper expression language here
|
||||||
cmd := cm.Commands[expr]
|
toks := shellwords.Split(expr)
|
||||||
|
if len(toks) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := cm.Commands[toks[0]]
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
return cmd.Do(ctx)
|
return cmd.Do(ctx.WithArgs(toks[1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("no such command: %v", expr)
|
return fmt.Errorf("no such command: %v", expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (cm *CommandMapping) DoEval(ctx *CommandContext, expr string) {
|
|
||||||
// if err := cm.Eval(ctx, expr); err != nil {
|
|
||||||
// ctx.ShowError(err)
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Registers the standard view navigation commands. These commands require the frame
|
// Registers the standard view navigation commands. These commands require the frame
|
||||||
func (cm *CommandMapping) RegisterViewCommands() {
|
func (cm *CommandMapping) RegisterViewCommands() {
|
||||||
cm.Define("move-down", "Moves the cursor down one row", "", gridNavOperation(func(grid *ui.Grid) { grid.MoveBy(0, 1) }))
|
cm.Define("move-down", "Moves the cursor down one row", "", gridNavOperation(func(grid *ui.Grid) { grid.MoveBy(0, 1) }))
|
||||||
|
|
@ -153,6 +154,34 @@ func (cm *CommandMapping) RegisterViewCommands() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
cm.Define("x-replace", "Performs a search and replace", "", func(ctx *CommandContext) error {
|
||||||
|
if len(ctx.Args()) != 2 {
|
||||||
|
return errors.New("Usage: x-replace MATCH REPLACEMENT")
|
||||||
|
}
|
||||||
|
|
||||||
|
match := ctx.Args()[0]
|
||||||
|
repl := ctx.Args()[1]
|
||||||
|
|
||||||
|
re, err := regexp.Compile(match)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid regexp: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
matchCount := 0
|
||||||
|
height, width := ctx.ModelVC().Model().Dimensions()
|
||||||
|
for r := 0; r < height; r++ {
|
||||||
|
for c := 0; c < width; c++ {
|
||||||
|
cell := ctx.ModelVC().Model().CellValue(r, c)
|
||||||
|
if re.FindStringIndex(cell) != nil {
|
||||||
|
ctx.ModelVC().SetCellValue(r, c, re.ReplaceAllString(cell, repl))
|
||||||
|
matchCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Frame().ShowMessage(fmt.Sprintf("Replaced %d matches", matchCount))
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
cm.Define("open-right", "Inserts a column to the right of the curser", "", func(ctx *CommandContext) error {
|
cm.Define("open-right", "Inserts a column to the right of the curser", "", func(ctx *CommandContext) error {
|
||||||
grid := ctx.Frame().Grid()
|
grid := ctx.Frame().Grid()
|
||||||
|
|
|
||||||
1
go.mod
1
go.mod
|
|
@ -3,6 +3,7 @@ module github.com/lmika/ted
|
||||||
go 1.15
|
go 1.15
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe
|
||||||
github.com/mattn/go-runewidth v0.0.9 // indirect
|
github.com/mattn/go-runewidth v0.0.9 // indirect
|
||||||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1
|
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1
|
||||||
)
|
)
|
||||||
|
|
|
||||||
2
go.sum
2
go.sum
|
|
@ -1,3 +1,5 @@
|
||||||
|
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe h1:1UXS/6OFkbi6JrihPykmYO1VtsABB02QQ+YmYYzTY18=
|
||||||
|
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe/go.mod h1:qpdOkLougV5Yry4Px9f1w1pNMavcr6Z67VW5Ro+vW5I=
|
||||||
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
|
||||||
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag=
|
github.com/nsf/termbox-go v0.0.0-20200418040025-38ba6e5628f1 h1:lh3PyZvY+B9nFliSGTn5uFuqQQJGuNrD0MLCokv09ag=
|
||||||
|
|
|
||||||
21
session.go
21
session.go
|
|
@ -1,8 +1,9 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lmika/ted/ui"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
||||||
|
"github.com/lmika/ted/ui"
|
||||||
)
|
)
|
||||||
|
|
||||||
// The session is responsible for managing the UI and the model and handling
|
// The session is responsible for managing the UI and the model and handling
|
||||||
|
|
@ -61,7 +62,7 @@ func (session *Session) KeyPressed(key rune, mod int) {
|
||||||
|
|
||||||
cmd := session.Commands.KeyMapping(key)
|
cmd := session.Commands.KeyMapping(key)
|
||||||
if cmd != nil {
|
if cmd != nil {
|
||||||
err := cmd.Do(&CommandContext{session})
|
err := cmd.Do(&CommandContext{session, nil})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
session.Frame.ShowMessage(err.Error())
|
session.Frame.ShowMessage(err.Error())
|
||||||
}
|
}
|
||||||
|
|
@ -71,6 +72,18 @@ func (session *Session) KeyPressed(key rune, mod int) {
|
||||||
// The command context used by the session
|
// The command context used by the session
|
||||||
type CommandContext struct {
|
type CommandContext struct {
|
||||||
session *Session
|
session *Session
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scc *CommandContext) WithArgs(args []string) *CommandContext {
|
||||||
|
return &CommandContext{
|
||||||
|
session: scc.session,
|
||||||
|
args: args,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (scc *CommandContext) Args() []string {
|
||||||
|
return scc.args
|
||||||
}
|
}
|
||||||
|
|
||||||
func (scc *CommandContext) ModelVC() *ModelViewCtrl {
|
func (scc *CommandContext) ModelVC() *ModelViewCtrl {
|
||||||
|
|
@ -125,10 +138,10 @@ func (sgm *SessionGridModel) CellAttributes(x int, y int) (fg, bg ui.Attribute)
|
||||||
} else if colAttrs.Marker != MarkerNone {
|
} else if colAttrs.Marker != MarkerNone {
|
||||||
return markerAttributes[colAttrs.Marker], 0
|
return markerAttributes[colAttrs.Marker], 0
|
||||||
}
|
}
|
||||||
return 0,0
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
|
||||||
var markerAttributes = map[Marker]ui.Attribute {
|
var markerAttributes = map[Marker]ui.Attribute{
|
||||||
MarkerRed: ui.ColorRed,
|
MarkerRed: ui.ColorRed,
|
||||||
MarkerGreen: ui.ColorGreen,
|
MarkerGreen: ui.ColorGreen,
|
||||||
MarkerBlue: ui.ColorBlue,
|
MarkerBlue: ui.ColorBlue,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ package ui
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// A text component. This simply renders a text string.
|
// A text component. This simply renders a text string.
|
||||||
type TextView struct {
|
type TextView struct {
|
||||||
|
|
@ -124,6 +124,8 @@ func (te *TextEntry) KeyPressed(key rune, mod int) {
|
||||||
if mod&ModKeyAlt != 0 {
|
if mod&ModKeyAlt != 0 {
|
||||||
te.backspaceWhile(unicode.IsSpace)
|
te.backspaceWhile(unicode.IsSpace)
|
||||||
te.backspaceWhile(func(r rune) bool { return !unicode.IsSpace(r) })
|
te.backspaceWhile(func(r rune) bool { return !unicode.IsSpace(r) })
|
||||||
|
} else if te.cursorOffset == 0 {
|
||||||
|
te.cancelAndExit()
|
||||||
} else {
|
} else {
|
||||||
te.backspace()
|
te.backspace()
|
||||||
}
|
}
|
||||||
|
|
@ -136,14 +138,18 @@ func (te *TextEntry) KeyPressed(key rune, mod int) {
|
||||||
te.OnEntry(te.value)
|
te.OnEntry(te.value)
|
||||||
}
|
}
|
||||||
} else if key == KeyCtrlC {
|
} else if key == KeyCtrlC {
|
||||||
if te.OnCancel != nil {
|
te.cancelAndExit()
|
||||||
te.OnCancel()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//panic(fmt.Sprintf("Entered key: '%x', mod: '%x'", key, mod))
|
//panic(fmt.Sprintf("Entered key: '%x', mod: '%x'", key, mod))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (te *TextEntry) cancelAndExit() {
|
||||||
|
if te.OnCancel != nil {
|
||||||
|
te.OnCancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Backspace
|
// Backspace
|
||||||
func (te *TextEntry) backspace() {
|
func (te *TextEntry) backspace() {
|
||||||
te.removeCharAtPos(te.cursorOffset - 1)
|
te.removeCharAtPos(te.cursorOffset - 1)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue