You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/08/05 10:30:09 UTC

[plc4x] 01/03: refactor(plc4xbrowser): split up main into ui and actions

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 8b9da2abdc0d1766c2da9e1416f738ccd7d88044
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Fri Aug 5 10:48:32 2022 +0200

    refactor(plc4xbrowser): split up main into ui and actions
---
 plc4go/tools/plc4xbrowser/actions.go         |  58 ++++++
 plc4go/tools/plc4xbrowser/commands.go        |   1 -
 plc4go/tools/plc4xbrowser/main.go            | 275 +--------------------------
 plc4go/tools/plc4xbrowser/{main.go => ui.go} |  93 +--------
 4 files changed, 63 insertions(+), 364 deletions(-)

diff --git a/plc4go/tools/plc4xbrowser/actions.go b/plc4go/tools/plc4xbrowser/actions.go
new file mode 100644
index 000000000..549661b1b
--- /dev/null
+++ b/plc4go/tools/plc4xbrowser/actions.go
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package main
+
+import (
+	"fmt"
+	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
+	"github.com/rivo/tview"
+	"github.com/rs/zerolog"
+	"github.com/rs/zerolog/log"
+)
+
+func initSubsystem() {
+	driverManager = plc4go.NewPlcDriverManager()
+
+	logLevel := zerolog.InfoLevel
+	if configuredLevel := config.LogLevel; configuredLevel != "" {
+		if parsedLevel, err := zerolog.ParseLevel(configuredLevel); err != nil {
+			panic(err)
+		} else {
+			logLevel = parsedLevel
+		}
+	}
+
+	log.Logger = log.
+		//// Enable below if you want to see the filenames
+		//With().Caller().Logger().
+		Output(zerolog.ConsoleWriter{Out: tview.ANSIWriter(consoleOutput)}).
+		Level(logLevel)
+
+	// We offset the commands executed with the last commands
+	commandsExecuted = len(config.History.Last10Commands)
+	outputCommandHistory()
+}
+
+func outputCommandHistory() {
+	_, _ = fmt.Fprintln(commandOutput, "[#0000ff]Last 10 commands[white]")
+	for i, command := range config.History.Last10Commands {
+		_, _ = fmt.Fprintf(commandOutput, "   [#00ff00]%d[white]: [\"%d\"]%s[\"\"]\n", i, i, command)
+	}
+}
diff --git a/plc4go/tools/plc4xbrowser/commands.go b/plc4go/tools/plc4xbrowser/commands.go
index 07aef6c90..930cdcab7 100644
--- a/plc4go/tools/plc4xbrowser/commands.go
+++ b/plc4go/tools/plc4xbrowser/commands.go
@@ -160,7 +160,6 @@ var rootCommand = Command{
 				} else {
 					return errors.Errorf("%s mode switch not yet implemented", connection)
 				}
-				return nil
 			},
 			parameterSuggestions: func(currentText string) (entries []string) {
 				for connectionsString, _ := range connections {
diff --git a/plc4go/tools/plc4xbrowser/main.go b/plc4go/tools/plc4xbrowser/main.go
index 283afc0bd..c0793b0b9 100644
--- a/plc4go/tools/plc4xbrowser/main.go
+++ b/plc4go/tools/plc4xbrowser/main.go
@@ -20,18 +20,8 @@
 package main
 
 import (
-	"fmt"
-	"github.com/pkg/errors"
 	"io"
-	"regexp"
-	"strconv"
 	"sync"
-	"time"
-
-	"github.com/gdamore/tcell/v2"
-	"github.com/rivo/tview"
-	"github.com/rs/zerolog"
-	"github.com/rs/zerolog/log"
 
 	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
 )
@@ -64,36 +54,6 @@ func init() {
 	connections = make(map[string]plc4go.PlcConnection)
 }
 
-func initSubsystem() {
-	driverManager = plc4go.NewPlcDriverManager()
-
-	logLevel := zerolog.InfoLevel
-	if configuredLevel := config.LogLevel; configuredLevel != "" {
-		if parsedLevel, err := zerolog.ParseLevel(configuredLevel); err != nil {
-			panic(err)
-		} else {
-			logLevel = parsedLevel
-		}
-	}
-
-	log.Logger = log.
-		//// Enable below if you want to see the filenames
-		//With().Caller().Logger().
-		Output(zerolog.ConsoleWriter{Out: tview.ANSIWriter(consoleOutput)}).
-		Level(logLevel)
-
-	// We offset the commands executed with the last commands
-	commandsExecuted = len(config.History.Last10Commands)
-	outputCommandHistory()
-}
-
-func outputCommandHistory() {
-	_, _ = fmt.Fprintln(commandOutput, "[#0000ff]Last 10 commands[white]")
-	for i, command := range config.History.Last10Commands {
-		_, _ = fmt.Fprintf(commandOutput, "   [#00ff00]%d[white]: [\"%d\"]%s[\"\"]\n", i, i, command)
-	}
-}
-
 var shutdownMutex sync.Mutex
 var hasShutdown bool
 
@@ -111,243 +71,10 @@ func shutdown() {
 }
 
 func main() {
-	application := tview.NewApplication()
-
-	newPrimitive := func(text string) tview.Primitive {
-		return tview.NewTextView().
-			SetTextAlign(tview.AlignCenter).
-			SetText(text)
-	}
-	connectionArea := buildConnectionArea(newPrimitive, application)
-	outputArea := buildOutputArea(newPrimitive, application)
-	commandArea := buildCommandArea(newPrimitive, application)
-
-	grid := tview.NewGrid().
-		SetRows(3, 0, 1).
-		SetColumns(30, 0, 30).
-		SetBorders(true).
-		AddItem(newPrimitive("PLC4X Browser"), 0, 0, 1, 3, 0, 0, false).
-		AddItem(newPrimitive("https://github.com/apache/plc4x"), 2, 0, 1, 3, 0, 0, false)
-
-	// Layout for screens narrower than 100 cells (connectionArea and side bar are hidden).
-	grid.AddItem(connectionArea, 0, 0, 0, 0, 0, 0, false).
-		AddItem(outputArea, 1, 0, 1, 3, 0, 0, false).
-		AddItem(commandArea, 0, 0, 0, 0, 0, 0, true)
-
-	// Layout for screens wider than 100 cells.
-	grid.AddItem(connectionArea, 1, 0, 1, 1, 0, 100, false).
-		AddItem(outputArea, 1, 1, 1, 1, 0, 100, false).
-		AddItem(commandArea, 1, 2, 1, 1, 0, 100, false)
-
-	application.SetRoot(grid, true).EnableMouse(true)
-
-	loadConfig()
-
-	initSubsystem()
-
-	application.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey {
-		switch event.Key() {
-		case tcell.KeyCtrlC:
-			shutdown()
-		}
-		return event
-	})
+	application := setupApplication()
 
 	if err := application.Run(); err != nil {
 		panic(err)
 	}
 	shutdown()
 }
-
-func buildConnectionArea(newPrimitive func(text string) tview.Primitive, application *tview.Application) tview.Primitive {
-	connectionAreaHeader := newPrimitive("Connections")
-	connectionArea := tview.NewGrid().
-		SetRows(3, 0, 10).
-		SetColumns(0).
-		AddItem(connectionAreaHeader, 0, 0, 1, 1, 0, 0, false)
-	{
-		connectionList := tview.NewList()
-		connectionsChanged = func() {
-			application.QueueUpdateDraw(func() {
-				connectionList.Clear()
-				for connectionString, connection := range connections {
-					connectionList.AddItem(connectionString, "", 0x0, func() {
-						//TODO: disconnect popup
-						_ = connection
-					})
-				}
-			})
-		}
-		connectionArea.AddItem(connectionList, 1, 0, 1, 1, 0, 0, false)
-		{
-			registeredDriverAreaHeader := newPrimitive("Registered drivers")
-			registeredDriverArea := tview.NewGrid().
-				SetRows(3, 0).
-				SetColumns(0).
-				AddItem(registeredDriverAreaHeader, 0, 0, 1, 1, 0, 0, false)
-			{
-				driverList := tview.NewList()
-				driverAdded = func(driver string) {
-					application.QueueUpdateDraw(func() {
-						driverList.AddItem(driver, "", 0x0, func() {
-							//TODO: disconnect popup
-						})
-					})
-				}
-				registeredDriverArea.AddItem(driverList, 1, 0, 1, 1, 0, 0, false)
-			}
-			connectionArea.AddItem(registeredDriverArea, 2, 0, 1, 1, 0, 0, false)
-		}
-
-	}
-	return connectionArea
-}
-
-func buildCommandArea(newPrimitive func(text string) tview.Primitive, application *tview.Application) tview.Primitive {
-	commandAreaHeader := newPrimitive("Commands")
-	commandArea := tview.NewGrid().
-		SetRows(3, 0, 3).
-		SetColumns(0).
-		AddItem(commandAreaHeader, 0, 0, 1, 1, 0, 0, false)
-	{
-		enteredCommandsView := tview.NewTextView().
-			SetDynamicColors(true).
-			SetRegions(true).
-			SetWordWrap(true).
-			SetChangedFunc(func() {
-				application.Draw()
-			})
-		commandOutput = enteredCommandsView
-		commandOutputClear = func() {
-			enteredCommandsView.SetText("")
-		}
-
-		commandArea.AddItem(enteredCommandsView, 1, 0, 1, 1, 0, 0, false)
-
-		commandInputField := tview.NewInputField().
-			SetLabel("$").
-			SetFieldWidth(30)
-		commandInputField.
-			SetDoneFunc(func(key tcell.Key) {
-				commandText := commandInputField.GetText()
-				if commandText == "quit" {
-					// TODO: maybe add a modal here
-					application.Stop()
-					return
-				}
-				commandsExecuted++
-				go func() {
-					commandHistoryShortcut, _ := regexp.Compile("^[0-9]$")
-					if commandHistoryShortcut.MatchString(commandText) {
-						atoi, _ := strconv.Atoi(commandHistoryShortcut.FindString(commandText))
-						if atoi < len(config.History.Last10Commands) {
-							commandText = config.History.Last10Commands[atoi]
-						} else {
-							_, _ = fmt.Fprintf(enteredCommandsView, "[#ff0000]%s %s[white]\n", time.Now().Format("04:05"), errors.Errorf("No such elements %d in command history", atoi))
-							return
-						}
-					}
-					_, _ = fmt.Fprintf(enteredCommandsView, "%s [\"%d\"]%s[\"\"]\n", time.Now().Format("04:05"), commandsExecuted, commandText)
-					if err := Execute(commandText); err != nil {
-						_, _ = fmt.Fprintf(enteredCommandsView, "[#ff0000]%s %s[white]\n", time.Now().Format("04:05"), err)
-						return
-					}
-					application.QueueUpdateDraw(func() {
-						commandInputField.SetText("")
-					})
-				}()
-			})
-		commandInputField.SetAutocompleteFunc(rootCommand.Completions)
-
-		enteredCommandsView.SetDoneFunc(func(key tcell.Key) {
-			currentSelection := enteredCommandsView.GetHighlights()
-			if key == tcell.KeyEnter {
-				if len(currentSelection) > 0 {
-					enteredCommandsView.Highlight()
-				} else {
-					enteredCommandsView.Highlight("0").ScrollToHighlight()
-				}
-				if len(currentSelection) == 1 {
-					// TODO: currently this is broken due to https://github.com/rivo/tview/issues/751
-					commandInputField.SetText(enteredCommandsView.GetRegionText(currentSelection[0]))
-					application.SetFocus(commandInputField)
-				}
-			} else if len(currentSelection) > 0 {
-				index, _ := strconv.Atoi(currentSelection[0])
-				if key == tcell.KeyTab {
-					index = (index + 1) % commandsExecuted
-				} else if key == tcell.KeyBacktab {
-					index = (index - 1 + commandsExecuted) % commandsExecuted
-				} else {
-					return
-				}
-				enteredCommandsView.Highlight(strconv.Itoa(index)).ScrollToHighlight()
-			}
-		})
-
-		commandArea.AddItem(commandInputField, 2, 0, 1, 1, 0, 0, true)
-	}
-	return commandArea
-}
-
-func buildOutputArea(newPrimitive func(text string) tview.Primitive, application *tview.Application) *tview.Grid {
-	outputAreaHeader := newPrimitive("Output")
-	outputArea := tview.NewGrid().
-		SetRows(3, 0, 10).
-		SetColumns(0).
-		AddItem(outputAreaHeader, 0, 0, 1, 1, 0, 0, false)
-	{
-		{
-			outputView := tview.NewTextView().
-				SetDynamicColors(true).
-				SetRegions(true).
-				SetWordWrap(true).
-				SetChangedFunc(func() {
-					application.Draw()
-				})
-			messageOutput = outputView
-			messageOutputClear = func() {
-				outputView.SetText("")
-			}
-
-			outputView.SetDoneFunc(func(key tcell.Key) {
-				currentSelection := outputView.GetHighlights()
-				if key == tcell.KeyEnter {
-					if len(currentSelection) > 0 {
-						outputView.Highlight()
-					} else {
-						outputView.Highlight("0").ScrollToHighlight()
-					}
-				} else if len(currentSelection) > 0 {
-					index, _ := strconv.Atoi(currentSelection[0])
-					if key == tcell.KeyTab {
-						index = (index + 1) % messagesReceived
-					} else if key == tcell.KeyBacktab {
-						index = (index - 1 + messagesReceived) % messagesReceived
-					} else {
-						return
-					}
-					outputView.Highlight(strconv.Itoa(index)).ScrollToHighlight()
-				}
-			})
-			outputView.SetBorder(false)
-			outputArea.AddItem(outputView, 1, 0, 1, 1, 0, 0, false)
-		}
-
-		{
-			consoleView := tview.NewTextView().
-				SetDynamicColors(true).
-				SetChangedFunc(func() {
-					application.Draw()
-				})
-			consoleOutput = consoleView
-			consoleOutputClear = func() {
-				consoleView.SetText("")
-			}
-
-			consoleView.SetBorder(false)
-			outputArea.AddItem(consoleView, 2, 0, 1, 1, 0, 0, false)
-		}
-	}
-	return outputArea
-}
diff --git a/plc4go/tools/plc4xbrowser/main.go b/plc4go/tools/plc4xbrowser/ui.go
similarity index 81%
copy from plc4go/tools/plc4xbrowser/main.go
copy to plc4go/tools/plc4xbrowser/ui.go
index 283afc0bd..139bb56c1 100644
--- a/plc4go/tools/plc4xbrowser/main.go
+++ b/plc4go/tools/plc4xbrowser/ui.go
@@ -21,96 +21,15 @@ package main
 
 import (
 	"fmt"
+	"github.com/gdamore/tcell/v2"
 	"github.com/pkg/errors"
-	"io"
+	"github.com/rivo/tview"
 	"regexp"
 	"strconv"
-	"sync"
 	"time"
-
-	"github.com/gdamore/tcell/v2"
-	"github.com/rivo/tview"
-	"github.com/rs/zerolog"
-	"github.com/rs/zerolog/log"
-
-	plc4go "github.com/apache/plc4x/plc4go/pkg/api"
-)
-
-var driverManager plc4go.PlcDriverManager
-var driverAdded func(string)
-var connections map[string]plc4go.PlcConnection
-var connectionsChanged func()
-
-var messagesReceived int
-var messageOutput io.Writer
-var messageOutputClear func()
-
-var consoleOutput io.Writer
-var consoleOutputClear func()
-
-var commandsExecuted int
-var commandOutput io.Writer
-var commandOutputClear func()
-
-type inputMode int
-
-const (
-	normalMode inputMode = iota
-	subscribeEditMode
 )
 
-func init() {
-	hasShutdown = false
-	connections = make(map[string]plc4go.PlcConnection)
-}
-
-func initSubsystem() {
-	driverManager = plc4go.NewPlcDriverManager()
-
-	logLevel := zerolog.InfoLevel
-	if configuredLevel := config.LogLevel; configuredLevel != "" {
-		if parsedLevel, err := zerolog.ParseLevel(configuredLevel); err != nil {
-			panic(err)
-		} else {
-			logLevel = parsedLevel
-		}
-	}
-
-	log.Logger = log.
-		//// Enable below if you want to see the filenames
-		//With().Caller().Logger().
-		Output(zerolog.ConsoleWriter{Out: tview.ANSIWriter(consoleOutput)}).
-		Level(logLevel)
-
-	// We offset the commands executed with the last commands
-	commandsExecuted = len(config.History.Last10Commands)
-	outputCommandHistory()
-}
-
-func outputCommandHistory() {
-	_, _ = fmt.Fprintln(commandOutput, "[#0000ff]Last 10 commands[white]")
-	for i, command := range config.History.Last10Commands {
-		_, _ = fmt.Fprintf(commandOutput, "   [#00ff00]%d[white]: [\"%d\"]%s[\"\"]\n", i, i, command)
-	}
-}
-
-var shutdownMutex sync.Mutex
-var hasShutdown bool
-
-func shutdown() {
-	shutdownMutex.Lock()
-	defer shutdownMutex.Unlock()
-	if hasShutdown {
-		return
-	}
-	for _, connection := range connections {
-		connection.Close()
-	}
-	saveConfig()
-	hasShutdown = true
-}
-
-func main() {
+func setupApplication() *tview.Application {
 	application := tview.NewApplication()
 
 	newPrimitive := func(text string) tview.Primitive {
@@ -152,11 +71,7 @@ func main() {
 		}
 		return event
 	})
-
-	if err := application.Run(); err != nil {
-		panic(err)
-	}
-	shutdown()
+	return application
 }
 
 func buildConnectionArea(newPrimitive func(text string) tview.Primitive, application *tview.Application) tview.Primitive {