about summary refs log tree commit diff stats
path: root/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'widgets')
-rw-r--r--widgets/account.go80
-rw-r--r--widgets/aerc.go2
-rw-r--r--widgets/exline.go8
-rw-r--r--widgets/msglist.go4
4 files changed, 62 insertions, 32 deletions
diff --git a/widgets/account.go b/widgets/account.go
index f5e24d2..f7b9f69 100644
--- a/widgets/account.go
+++ b/widgets/account.go
@@ -14,7 +14,8 @@ import (
 )
 
 type AccountView struct {
-	conf         *config.AccountConfig
+	acct         *config.AccountConfig
+	conf         *config.AercConfig
 	dirlist      *DirectoryList
 	grid         *ui.Grid
 	logger       *log.Logger
@@ -23,12 +24,13 @@ type AccountView struct {
 	runCmd       func(cmd string) error
 	msglist      *MessageList
 	msgStores    map[string]*MessageStore
+	pendingKeys  []config.KeyStroke
 	statusline   *StatusLine
 	statusbar    *ui.Stack
 	worker       *types.Worker
 }
 
-func NewAccountView(conf *config.AccountConfig,
+func NewAccountView(conf *config.AercConfig, acct *config.AccountConfig,
 	logger *log.Logger, runCmd func(cmd string) error) *AccountView {
 
 	statusbar := ui.NewStack()
@@ -44,24 +46,25 @@ func NewAccountView(conf *config.AccountConfig,
 	})
 	grid.AddChild(statusbar).At(1, 1)
 
-	worker, err := worker.NewWorker(conf.Source, logger)
+	worker, err := worker.NewWorker(acct.Source, logger)
 	if err != nil {
 		statusline.Set(fmt.Sprintf("%s", err))
 		return &AccountView{
-			conf:       conf,
+			acct:       acct,
 			grid:       grid,
 			logger:     logger,
 			statusline: statusline,
 		}
 	}
 
-	dirlist := NewDirectoryList(conf, logger, worker)
+	dirlist := NewDirectoryList(acct, logger, worker)
 	grid.AddChild(ui.NewBordered(dirlist, ui.BORDER_RIGHT)).Span(2, 1)
 
 	msglist := NewMessageList(logger)
 	grid.AddChild(msglist).At(0, 1)
 
-	acct := &AccountView{
+	view := &AccountView{
+		acct:       acct,
 		conf:       conf,
 		dirlist:    dirlist,
 		grid:       grid,
@@ -79,19 +82,19 @@ func NewAccountView(conf *config.AccountConfig,
 		for {
 			msg := <-worker.Messages
 			msg = worker.ProcessMessage(msg)
-			acct.onMessage(msg)
+			view.onMessage(msg)
 		}
 	}()
 
-	worker.PostAction(&types.Configure{Config: conf}, nil)
-	worker.PostAction(&types.Connect{}, acct.connected)
+	worker.PostAction(&types.Configure{Config: acct}, nil)
+	worker.PostAction(&types.Connect{}, view.connected)
 	statusline.Set("Connecting...")
 
-	return acct
+	return view
 }
 
 func (acct *AccountView) Name() string {
-	return acct.conf.Name
+	return acct.acct.Name
 }
 
 func (acct *AccountView) Children() []ui.Drawable {
@@ -112,28 +115,51 @@ func (acct *AccountView) Draw(ctx *ui.Context) {
 	acct.grid.Draw(ctx)
 }
 
+func (acct *AccountView) beginExCommand() {
+	exline := NewExLine(func(command string) {
+		err := acct.runCmd(command)
+		if err != nil {
+			acct.statusline.Push(" "+err.Error(), 10*time.Second).
+				Color(tcell.ColorRed, tcell.ColorWhite)
+		}
+		acct.statusbar.Pop()
+		acct.interactive = nil
+	}, func() {
+		acct.statusbar.Pop()
+		acct.interactive = nil
+	})
+	acct.interactive = exline
+	acct.statusbar.Push(exline)
+}
+
 func (acct *AccountView) Event(event tcell.Event) bool {
 	if acct.interactive != nil {
 		return acct.interactive.Event(event)
 	}
+
 	switch event := event.(type) {
 	case *tcell.EventKey:
-		if event.Rune() == ':' {
-			exline := NewExLine(func(command string) {
-				err := acct.runCmd(command)
-				if err != nil {
-					acct.statusline.Push(" "+err.Error(), 10*time.Second).
-						Color(tcell.ColorRed, tcell.ColorWhite)
-				}
-				acct.statusbar.Pop()
-				acct.interactive = nil
-			}, func() {
-				acct.statusbar.Pop()
-				acct.interactive = nil
-			})
-			acct.interactive = exline
-			acct.statusbar.Push(exline)
-			return true
+		acct.pendingKeys = append(acct.pendingKeys, config.KeyStroke{
+			Key:  event.Key(),
+			Rune: event.Rune(),
+		})
+		result, output := acct.conf.Lbinds.GetBinding(acct.pendingKeys)
+		switch result {
+		case config.BINDING_FOUND:
+			acct.pendingKeys = []config.KeyStroke{}
+			for _, stroke := range output {
+				simulated := tcell.NewEventKey(
+					stroke.Key, stroke.Rune, tcell.ModNone)
+				acct.Event(simulated)
+			}
+		case config.BINDING_INCOMPLETE:
+			return false
+		case config.BINDING_NOT_FOUND:
+			acct.pendingKeys = []config.KeyStroke{}
+			if event.Rune() == ':' {
+				acct.beginExCommand()
+				return true
+			}
 		}
 	}
 	return false
diff --git a/widgets/aerc.go b/widgets/aerc.go
index bf545f9..e7f4583 100644
--- a/widgets/aerc.go
+++ b/widgets/aerc.go
@@ -45,7 +45,7 @@ func NewAerc(conf *config.AercConfig, logger *log.Logger,
 	}
 
 	for _, acct := range conf.Accounts {
-		view := NewAccountView(&acct, logger, cmd)
+		view := NewAccountView(conf, &acct, logger, cmd)
 		aerc.accounts[acct.Name] = view
 		tabs.Add(view, acct.Name)
 	}
diff --git a/widgets/exline.go b/widgets/exline.go
index 77f1414..7eff74a 100644
--- a/widgets/exline.go
+++ b/widgets/exline.go
@@ -121,10 +121,14 @@ func (ex *ExLine) Event(event tcell.Event) bool {
 		case tcell.KeyCtrlW:
 			ex.deleteWord()
 		case tcell.KeyEnter:
-			ex.ctx.HideCursor()
+			if ex.ctx != nil {
+				ex.ctx.HideCursor()
+			}
 			ex.commit(string(ex.command))
 		case tcell.KeyEsc, tcell.KeyCtrlC:
-			ex.ctx.HideCursor()
+			if ex.ctx != nil {
+				ex.ctx.HideCursor()
+			}
 			ex.cancel()
 		case tcell.KeyRune:
 			ex.insert(event.Rune())
diff --git a/widgets/msglist.go b/widgets/msglist.go
index 36d7f7a..5ba75a8 100644
--- a/widgets/msglist.go
+++ b/widgets/msglist.go
@@ -184,10 +184,10 @@ func (ml *MessageList) SetStore(store *MessageStore) {
 func (ml *MessageList) nextPrev(delta int) {
 	ml.selected += delta
 	if ml.selected < 0 {
-		ml.selected = len(ml.store.Uids) - 1
+		ml.selected = 0
 	}
 	if ml.selected >= len(ml.store.Uids) {
-		ml.selected = 0
+		ml.selected = len(ml.store.Uids) - 1
 	}
 	// TODO: scrolling
 	ml.Invalidate()