Split command system from main view
This commit is contained in:
		
							
								
								
									
										128
									
								
								ui/command-processor.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								ui/command-processor.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					// gomuks - A terminal Matrix client written in Go.
 | 
				
			||||||
 | 
					// Copyright (C) 2018 Tulir Asokan
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"maunium.net/go/gomuks/interface"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"maunium.net/go/gomuks/config"
 | 
				
			||||||
 | 
						"maunium.net/go/gomuks/debug"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type gomuksPointerContainer struct {
 | 
				
			||||||
 | 
						MainView *MainView
 | 
				
			||||||
 | 
						UI       *GomuksUI
 | 
				
			||||||
 | 
						Matrix   ifc.MatrixContainer
 | 
				
			||||||
 | 
						Config   *config.Config
 | 
				
			||||||
 | 
						Gomuks   ifc.Gomuks
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Command struct {
 | 
				
			||||||
 | 
						gomuksPointerContainer
 | 
				
			||||||
 | 
						Handler *CommandProcessor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						Room     *RoomView
 | 
				
			||||||
 | 
						Command  string
 | 
				
			||||||
 | 
						Args     []string
 | 
				
			||||||
 | 
						OrigText string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (cmd *Command) Reply(message string, args ...interface{}) {
 | 
				
			||||||
 | 
						cmd.Room.AddServiceMessage(fmt.Sprintf(message, args...))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Alias struct {
 | 
				
			||||||
 | 
						NewCommand string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (alias *Alias) Process(cmd *Command) *Command {
 | 
				
			||||||
 | 
						cmd.Command = alias.NewCommand
 | 
				
			||||||
 | 
						return cmd
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CommandHandler func(cmd *Command)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CommandProcessor struct {
 | 
				
			||||||
 | 
						gomuksPointerContainer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						aliases  map[string]*Alias
 | 
				
			||||||
 | 
						commands map[string]CommandHandler
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCommandProcessor(parent *MainView) *CommandProcessor {
 | 
				
			||||||
 | 
						return &CommandProcessor{
 | 
				
			||||||
 | 
							gomuksPointerContainer: gomuksPointerContainer{
 | 
				
			||||||
 | 
								MainView: parent,
 | 
				
			||||||
 | 
								UI:       parent.parent,
 | 
				
			||||||
 | 
								Matrix:   parent.matrix,
 | 
				
			||||||
 | 
								Config:   parent.config,
 | 
				
			||||||
 | 
								Gomuks:   parent.gmx,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							aliases: map[string]*Alias{
 | 
				
			||||||
 | 
								"part": {"leave"},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							commands: map[string]CommandHandler{
 | 
				
			||||||
 | 
								"unknown-command": cmdUnknownCommand,
 | 
				
			||||||
 | 
								"help":            cmdHelp,
 | 
				
			||||||
 | 
								"me":              cmdMe,
 | 
				
			||||||
 | 
								"quit":            cmdQuit,
 | 
				
			||||||
 | 
								"clearcache":      cmdClearCache,
 | 
				
			||||||
 | 
								"leave":           cmdLeave,
 | 
				
			||||||
 | 
								"join":            cmdJoin,
 | 
				
			||||||
 | 
								"uitoggle":        cmdUIToggle,
 | 
				
			||||||
 | 
								"logout":          cmdLogout,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ch *CommandProcessor) ParseCommand(roomView *RoomView, text string) *Command {
 | 
				
			||||||
 | 
						if text[0] != '/' || len(text) < 2 {
 | 
				
			||||||
 | 
							return nil
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						text = text[1:]
 | 
				
			||||||
 | 
						args := strings.SplitN(text, " ", 2)
 | 
				
			||||||
 | 
						command := strings.ToLower(args[0])
 | 
				
			||||||
 | 
						args = args[1:]
 | 
				
			||||||
 | 
						return &Command{
 | 
				
			||||||
 | 
							gomuksPointerContainer: ch.gomuksPointerContainer,
 | 
				
			||||||
 | 
							Handler:                ch,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Room:     roomView,
 | 
				
			||||||
 | 
							Command:  command,
 | 
				
			||||||
 | 
							Args:     args,
 | 
				
			||||||
 | 
							OrigText: text,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (ch *CommandProcessor) HandleCommand(cmd *Command) {
 | 
				
			||||||
 | 
						defer debug.Recover()
 | 
				
			||||||
 | 
						if cmd == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if alias, ok := ch.aliases[cmd.Command]; ok {
 | 
				
			||||||
 | 
							cmd = alias.Process(cmd)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if cmd == nil {
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if handler, ok := ch.commands[cmd.Command]; ok {
 | 
				
			||||||
 | 
							handler(cmd)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmdUnknownCommand(cmd)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										99
									
								
								ui/commands.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								ui/commands.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					// gomuks - A terminal Matrix client written in Go.
 | 
				
			||||||
 | 
					// Copyright (C) 2018 Tulir Asokan
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					// it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					// the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					// (at your option) any later version.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// This program is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					// but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					// GNU General Public License for more details.
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					// along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package ui
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"maunium.net/go/gomuks/debug"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdMe(cmd *Command) {
 | 
				
			||||||
 | 
						text := strings.Join(cmd.Args, " ")
 | 
				
			||||||
 | 
						tempMessage := cmd.Room.NewTempMessage("m.emote", text)
 | 
				
			||||||
 | 
						go cmd.MainView.sendTempMessage(cmd.Room, tempMessage, text)
 | 
				
			||||||
 | 
						cmd.UI.Render()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdQuit(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Gomuks.Stop()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdClearCache(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Config.Clear()
 | 
				
			||||||
 | 
						cmd.Gomuks.Stop()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdUnknownCommand(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Reply("Unknown command \"%s\". Try \"/help\" for help.", cmd.Command)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdHelp(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Reply("Known command. Don't try \"/help\" for help.")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdLeave(cmd *Command) {
 | 
				
			||||||
 | 
						err := cmd.Matrix.LeaveRoom(cmd.Room.MxRoom().ID)
 | 
				
			||||||
 | 
						debug.Print("Leave room error:", err)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							cmd.MainView.RemoveRoom(cmd.Room.MxRoom())
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdJoin(cmd *Command) {
 | 
				
			||||||
 | 
						if len(cmd.Args) == 0 {
 | 
				
			||||||
 | 
							cmd.Reply("Usage: /join <room>")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						identifer := cmd.Args[0]
 | 
				
			||||||
 | 
						server := ""
 | 
				
			||||||
 | 
						if len(cmd.Args) > 1 {
 | 
				
			||||||
 | 
							server = cmd.Args[1]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						room, err := cmd.Matrix.JoinRoom(identifer, server)
 | 
				
			||||||
 | 
						debug.Print("Join room error:", err)
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							cmd.MainView.AddRoom(room)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdUIToggle(cmd *Command) {
 | 
				
			||||||
 | 
						if len(cmd.Args) == 0 {
 | 
				
			||||||
 | 
							cmd.Reply("Usage: /uitoggle <rooms/users/baremessages>")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						switch cmd.Args[0] {
 | 
				
			||||||
 | 
						case "rooms":
 | 
				
			||||||
 | 
							cmd.MainView.hideRoomList = !cmd.MainView.hideRoomList
 | 
				
			||||||
 | 
							cmd.Config.Preferences.HideRoomList = cmd.MainView.hideRoomList
 | 
				
			||||||
 | 
						case "users":
 | 
				
			||||||
 | 
							cmd.MainView.hideUserList = !cmd.MainView.hideUserList
 | 
				
			||||||
 | 
							cmd.Config.Preferences.HideUserList = cmd.MainView.hideUserList
 | 
				
			||||||
 | 
						case "baremessages":
 | 
				
			||||||
 | 
							cmd.MainView.bareMessages = !cmd.MainView.bareMessages
 | 
				
			||||||
 | 
							cmd.Config.Preferences.BareMessageView = cmd.MainView.bareMessages
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							cmd.Reply("Usage: /uitoggle <rooms/users/baremessages>")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmd.UI.Render()
 | 
				
			||||||
 | 
						cmd.UI.Render()
 | 
				
			||||||
 | 
						go cmd.Matrix.SendPreferencesToMatrix()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func cmdLogout(cmd *Command) {
 | 
				
			||||||
 | 
						cmd.Matrix.Logout()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -18,7 +18,6 @@ package ui
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"strings"
 | 
					 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
	"unicode"
 | 
						"unicode"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,9 +39,10 @@ import (
 | 
				
			|||||||
type MainView struct {
 | 
					type MainView struct {
 | 
				
			||||||
	*tview.Flex
 | 
						*tview.Flex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	roomList *RoomList
 | 
						roomList     *RoomList
 | 
				
			||||||
	roomView *tview.Pages
 | 
						roomView     *tview.Pages
 | 
				
			||||||
	rooms    map[string]*RoomView
 | 
						rooms        map[string]*RoomView
 | 
				
			||||||
 | 
						cmdProcessor *CommandProcessor
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lastFocusTime time.Time
 | 
						lastFocusTime time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -73,6 +73,7 @@ func (ui *GomuksUI) NewMainView() tview.Primitive {
 | 
				
			|||||||
		hideRoomList: prefs.HideRoomList,
 | 
							hideRoomList: prefs.HideRoomList,
 | 
				
			||||||
		bareMessages: prefs.BareMessageView,
 | 
							bareMessages: prefs.BareMessageView,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						mainView.cmdProcessor = NewCommandProcessor(mainView)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mainView.
 | 
						mainView.
 | 
				
			||||||
		SetDirection(tview.FlexColumn).
 | 
							SetDirection(tview.FlexColumn).
 | 
				
			||||||
@@ -133,10 +134,8 @@ func (view *MainView) InputSubmit(roomView *RoomView, text string) {
 | 
				
			|||||||
	if len(text) == 0 {
 | 
						if len(text) == 0 {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	} else if text[0] == '/' {
 | 
						} else if text[0] == '/' {
 | 
				
			||||||
		args := strings.SplitN(text, " ", 2)
 | 
							cmd := view.cmdProcessor.ParseCommand(roomView, text)
 | 
				
			||||||
		command := strings.ToLower(args[0])
 | 
							go view.cmdProcessor.HandleCommand(cmd)
 | 
				
			||||||
		args = args[1:]
 | 
					 | 
				
			||||||
		go view.HandleCommand(roomView, command, args)
 | 
					 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		view.SendMessage(roomView, text)
 | 
							view.SendMessage(roomView, text)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -168,72 +167,6 @@ func (view *MainView) sendTempMessage(roomView *RoomView, tempMessage ifc.Messag
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (view *MainView) HandleCommand(roomView *RoomView, command string, args []string) {
 | 
					 | 
				
			||||||
	defer debug.Recover()
 | 
					 | 
				
			||||||
	debug.Print("Handling command", command, args)
 | 
					 | 
				
			||||||
	switch command {
 | 
					 | 
				
			||||||
	case "/me":
 | 
					 | 
				
			||||||
		text := strings.Join(args, " ")
 | 
					 | 
				
			||||||
		tempMessage := roomView.NewTempMessage("m.emote", text)
 | 
					 | 
				
			||||||
		go view.sendTempMessage(roomView, tempMessage, text)
 | 
					 | 
				
			||||||
		view.parent.Render()
 | 
					 | 
				
			||||||
	case "/quit":
 | 
					 | 
				
			||||||
		view.gmx.Stop()
 | 
					 | 
				
			||||||
	case "/clearcache":
 | 
					 | 
				
			||||||
		view.config.Clear()
 | 
					 | 
				
			||||||
		view.gmx.Stop()
 | 
					 | 
				
			||||||
	case "/panic":
 | 
					 | 
				
			||||||
		panic("This is a test panic.")
 | 
					 | 
				
			||||||
	case "/part", "/leave":
 | 
					 | 
				
			||||||
		err := view.matrix.LeaveRoom(roomView.Room.ID)
 | 
					 | 
				
			||||||
		debug.Print("Leave room error:", err)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			view.RemoveRoom(roomView.Room)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case "/uitoggle":
 | 
					 | 
				
			||||||
		if len(args) == 0 {
 | 
					 | 
				
			||||||
			roomView.AddServiceMessage("Usage: /uitoggle <rooms/users/baremessages>")
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		switch args[0] {
 | 
					 | 
				
			||||||
		case "rooms":
 | 
					 | 
				
			||||||
			view.hideRoomList = !view.hideRoomList
 | 
					 | 
				
			||||||
			view.config.Preferences.HideRoomList = view.hideRoomList
 | 
					 | 
				
			||||||
		case "users":
 | 
					 | 
				
			||||||
			view.hideUserList = !view.hideUserList
 | 
					 | 
				
			||||||
			view.config.Preferences.HideUserList = view.hideUserList
 | 
					 | 
				
			||||||
		case "baremessages":
 | 
					 | 
				
			||||||
			view.bareMessages = !view.bareMessages
 | 
					 | 
				
			||||||
			view.config.Preferences.BareMessageView = view.bareMessages
 | 
					 | 
				
			||||||
		default:
 | 
					 | 
				
			||||||
			roomView.AddServiceMessage("Usage: /uitoggle <rooms/users/baremessages>")
 | 
					 | 
				
			||||||
			return
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		view.parent.Render()
 | 
					 | 
				
			||||||
		view.parent.Render()
 | 
					 | 
				
			||||||
		go view.matrix.SendPreferencesToMatrix()
 | 
					 | 
				
			||||||
	case "/join":
 | 
					 | 
				
			||||||
		if len(args) == 0 {
 | 
					 | 
				
			||||||
			roomView.AddServiceMessage("Usage: /join <room>")
 | 
					 | 
				
			||||||
			break
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		identifer := args[0]
 | 
					 | 
				
			||||||
		server := ""
 | 
					 | 
				
			||||||
		if len(args) > 1 {
 | 
					 | 
				
			||||||
			server = args[1]
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		room, err := view.matrix.JoinRoom(identifer, server)
 | 
					 | 
				
			||||||
		debug.Print("Join room error:", err)
 | 
					 | 
				
			||||||
		if err == nil {
 | 
					 | 
				
			||||||
			view.AddRoom(room)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	case "/logout":
 | 
					 | 
				
			||||||
		view.matrix.Logout()
 | 
					 | 
				
			||||||
	default:
 | 
					 | 
				
			||||||
		roomView.AddServiceMessage("Unknown command.")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (view *MainView) ShowBare(roomView *RoomView) {
 | 
					func (view *MainView) ShowBare(roomView *RoomView) {
 | 
				
			||||||
	_, height := view.parent.app.GetScreen().Size()
 | 
						_, height := view.parent.app.GetScreen().Size()
 | 
				
			||||||
	view.parent.app.Suspend(func() {
 | 
						view.parent.app.Suspend(func() {
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user