A few minor feature
Added automatic resizing of the columns when loading a model Added colouring of the currently search for cell
This commit is contained in:
parent
3ee6cbf514
commit
9267fc92a7
|
|
@ -126,12 +126,17 @@ func (cm *CommandMapping) RegisterViewCommands() {
|
|||
})
|
||||
cm.Define("search", "Search for a cell", "", func(ctx *CommandContext) error {
|
||||
ctx.Frame().Prompt(PromptOptions{Prompt: "/"}, func(res string) error {
|
||||
if res == "" {
|
||||
ctx.Session().SetLastSearch(nil)
|
||||
return nil
|
||||
}
|
||||
|
||||
re, err := regexp.Compile(res)
|
||||
if err != nil {
|
||||
return fmt.Errorf("invalid regexp: %v", err)
|
||||
}
|
||||
|
||||
ctx.session.LastSearch = re
|
||||
ctx.Session().SetLastSearch(re)
|
||||
return ctx.Session().Commands.Eval(ctx, "search-next")
|
||||
})
|
||||
return nil
|
||||
|
|
@ -252,6 +257,28 @@ func (cm *CommandMapping) RegisterViewCommands() {
|
|||
cm.Define("mark-row-red", "Set row marker to red", "", func(ctx *CommandContext) error {
|
||||
_, cellY := ctx.Frame().Grid().CellPosition()
|
||||
|
||||
namedArgs, _ := extractNamedArgs(ctx.args)
|
||||
if rowMatch, hasRowMatch := namedArgs["row-match"]; hasRowMatch {
|
||||
rows, cols := ctx.ModelVC().Model().Dimensions()
|
||||
|
||||
for r := 0; r < rows; r++ {
|
||||
rowMatches := false
|
||||
for c := 0; c < cols; c++ {
|
||||
cellVal := ctx.ModelVC().Model().CellValue(r, c)
|
||||
if cellVal == rowMatch {
|
||||
rowMatches = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if rowMatches {
|
||||
attrs := ctx.ModelVC().RowAttrs(r)
|
||||
attrs.Marker = MarkerRed
|
||||
ctx.ModelVC().SetRowAttrs(r, attrs)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
attrs := ctx.ModelVC().RowAttrs(cellY)
|
||||
attrs.Marker = MarkerRed
|
||||
ctx.ModelVC().SetRowAttrs(cellY, attrs)
|
||||
|
|
@ -495,3 +522,28 @@ func gridNavOperation(op func(grid *ui.Grid)) func(ctx *CommandContext) error {
|
|||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// extractNamedArgs will extract out any arguments of the form '-name value' and stick it in a map.
|
||||
// Any non-named arguments will be extracted out as positional. If an argument only has a name, it
|
||||
// will be added to the map with the empty string as the value.
|
||||
func extractNamedArgs(args []string) (namedArgs map[string]string, positionalArgs []string) {
|
||||
for len(args) > 0 {
|
||||
if args[0][0] == '-' {
|
||||
if namedArgs == nil {
|
||||
namedArgs = make(map[string]string)
|
||||
}
|
||||
|
||||
if len(args) >= 2 && args[1][0] != '-' {
|
||||
namedArgs[args[0][1:]] = args[1]
|
||||
args = args[2:]
|
||||
} else {
|
||||
namedArgs[args[0][1:]] = ""
|
||||
args = args[1:]
|
||||
}
|
||||
} else {
|
||||
positionalArgs = append(positionalArgs, args[0])
|
||||
args = args[1:]
|
||||
}
|
||||
}
|
||||
return namedArgs, positionalArgs
|
||||
}
|
||||
|
|
|
|||
18
go.mod
18
go.mod
|
|
@ -1,11 +1,21 @@
|
|||
module github.com/lmika/ted
|
||||
|
||||
go 1.15
|
||||
go 1.22
|
||||
|
||||
require (
|
||||
github.com/gdamore/tcell v1.4.0
|
||||
github.com/lmika/shellwords v0.0.0-20140714114018-ce258dd729fe
|
||||
github.com/mattn/go-runewidth v0.0.10 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/stretchr/testify v1.7.5 // indirect
|
||||
github.com/stretchr/testify v1.7.5
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/gdamore/encoding v1.0.0 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.0.3 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 // indirect
|
||||
golang.org/x/text v0.3.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
3
go.sum
3
go.sum
|
|
@ -14,12 +14,10 @@ github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRR
|
|||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.5 h1:s5PTfem8p8EbKQOctVV53k6jCJt3UX4IEJzwh+C324Q=
|
||||
|
|
@ -28,6 +26,7 @@ golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756 h1:9nuHUbU8dRnRRfj9KjWUVrJeo
|
|||
golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
|
|
|
|||
1
main.go
1
main.go
|
|
@ -30,6 +30,7 @@ func main() {
|
|||
frame := NewFrame(uiManager)
|
||||
session := NewSession(uiManager, frame, codecBuilder(flag.Arg(0)))
|
||||
session.LoadFromSource()
|
||||
session.ResizeToBestFit()
|
||||
|
||||
uiManager.SetRootComponent(frame.RootComponent())
|
||||
frame.enterMode(GridMode)
|
||||
|
|
|
|||
34
session.go
34
session.go
|
|
@ -6,6 +6,12 @@ import (
|
|||
"github.com/lmika/ted/ui"
|
||||
)
|
||||
|
||||
const (
|
||||
bestFixRightMargin = 2
|
||||
bestFixMinColumnSize = 8
|
||||
bestFixMaxColumnSize = 32
|
||||
)
|
||||
|
||||
// The session is responsible for managing the UI and the model and handling
|
||||
// the interaction between the two and the user.
|
||||
type Session struct {
|
||||
|
|
@ -55,6 +61,23 @@ func (session *Session) LoadFromSource() {
|
|||
session.modelController.SetModel(newModel)
|
||||
}
|
||||
|
||||
func (sesion *Session) ResizeToBestFit() {
|
||||
mr, mc := sesion.model.Dimensions()
|
||||
colMaxSize := make([]int, mc)
|
||||
for c := 0; c < mc; c++ {
|
||||
colMaxSize[c] = bestFixMinColumnSize
|
||||
for r := 0; r < mr; r++ {
|
||||
colMaxSize[c] = max(colMaxSize[c], len(sesion.model.CellValue(r, c))+bestFixRightMargin)
|
||||
}
|
||||
}
|
||||
|
||||
for c, ml := range colMaxSize {
|
||||
sesion.modelController.SetColAttrs(c, SliceAttr{
|
||||
Size: min(ml, bestFixMaxColumnSize),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Input from the frame
|
||||
func (session *Session) KeyPressed(key rune, mod int) {
|
||||
// Add the mod key modifier
|
||||
|
|
@ -71,6 +94,11 @@ func (session *Session) KeyPressed(key rune, mod int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *Session) SetLastSearch(re *regexp.Regexp) {
|
||||
s.LastSearch = re
|
||||
s.modelController.lastSearchRegexp = re
|
||||
}
|
||||
|
||||
// The command context used by the session
|
||||
type CommandContext struct {
|
||||
session *Session
|
||||
|
|
@ -132,6 +160,12 @@ func (sgm *SessionGridModel) CellValue(x int, y int) string {
|
|||
}
|
||||
|
||||
func (sgm *SessionGridModel) CellAttributes(x int, y int) (fg, bg ui.Attribute) {
|
||||
if sgm.GridViewModel.lastSearchRegexp != nil {
|
||||
if sgm.GridViewModel.lastSearchRegexp.MatchString(sgm.GridViewModel.Model().CellValue(y, x)) {
|
||||
return ui.ColorMagenta, 0
|
||||
}
|
||||
}
|
||||
|
||||
rowAttrs := sgm.GridViewModel.RowAttrs(y)
|
||||
colAttrs := sgm.GridViewModel.ColAttrs(y)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,14 @@ package main
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
type ModelViewCtrl struct {
|
||||
model Model
|
||||
rowAttrs []SliceAttr
|
||||
colAttrs []SliceAttr
|
||||
lastSearchRegexp *regexp.Regexp
|
||||
}
|
||||
|
||||
func NewGridViewModel(model Model) *ModelViewCtrl {
|
||||
|
|
@ -16,6 +18,10 @@ func NewGridViewModel(model Model) *ModelViewCtrl {
|
|||
return gvm
|
||||
}
|
||||
|
||||
func (gvm *ModelViewCtrl) SetLastSearchRegexp(r *regexp.Regexp) {
|
||||
gvm.lastSearchRegexp = r
|
||||
}
|
||||
|
||||
func (gvm *ModelViewCtrl) Model() Model {
|
||||
return gvm.model
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue