master > master: code - go project hinzugefügt

This commit is contained in:
RD 2021-10-30 10:19:16 +02:00
parent 37dea15b2b
commit f4287dfd8f
12 changed files with 669 additions and 0 deletions

15
code/golang/go.mod Normal file
View File

@ -0,0 +1,15 @@
module ads
go 1.17
require (
github.com/akamensky/argparse v1.3.1
github.com/davecgh/go-spew v1.1.1
github.com/lithammer/dedent v1.1.0
github.com/pmezard/go-difflib v1.0.0
github.com/slongfield/pyfmt v0.0.0-20180124071345-020a7cb18bca
github.com/stretchr/objx v0.1.0
github.com/stretchr/testify v1.7.0
golang.org/x/tools v0.1.7
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

View File

@ -0,0 +1,116 @@
package logging
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"os"
"ads/internal/core/utils"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES
* ---------------------------------------------------------------- */
var quietmode bool = false
var debugmode bool = false
var ansimode bool = true
var loggingPrefix string = ""
var force bool = false
var tagAll bool = false
func GetQuietMode() bool {
return quietmode
}
func SetQuietMode(mode bool) {
quietmode = mode
}
func GetDebugMode() bool {
return debugmode
}
func SetDebugMode(mode bool) {
debugmode = mode
}
func GetAnsiMode() bool {
return ansimode
}
func SetAnsiMode(mode bool) {
ansimode = mode
}
func GetForce() bool {
return force
}
func SetForce(mode bool) {
force = mode
}
func SetTagAll(mode bool) {
tagAll = mode
}
/* ---------------------------------------------------------------- *
* METHOD logging
* ---------------------------------------------------------------- */
func logGeneric(tag string, lines ...interface{}) {
if !force && quietmode {
return
}
if !(tag == "") {
tag = tag + " "
}
for _, line := range lines {
_line := fmt.Sprintf("%[1]s%[2]s%[3]v", loggingPrefix, tag, line)
if !ansimode {
_line = utils.StripAnsi(_line)
}
fmt.Println(_line)
if !tagAll {
tag = ""
}
}
}
func LogPlain(lines ...interface{}) {
SetTagAll(false)
logGeneric("", lines...)
}
func LogInfo(lines ...interface{}) {
SetTagAll(true)
logGeneric("[\033[94;1mINFO\033[0m]", lines...)
}
func LogDebug(lines ...interface{}) {
if !debugmode {
return
}
SetTagAll(true)
logGeneric("[\033[96;1mDEBUG\033[0m]", lines...)
}
func LogWarn(lines ...interface{}) {
SetTagAll(false)
logGeneric("[\033[93;1mWARNING\033[0m]", lines...)
}
func LogError(lines ...interface{}) {
SetTagAll(false)
logGeneric("[\033[91;1mERROR\033[0m]", lines...)
}
func LogFatal(lines ...interface{}) {
SetTagAll(false)
logGeneric("[\033[91;1mFATAL\033[0m]", lines...)
os.Exit(1)
}

View File

@ -0,0 +1,85 @@
package utils
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"reflect"
)
/* ---------------------------------------------------------------- *
* METHOD array contains
* ---------------------------------------------------------------- */
func ArrayContains(x interface{}, elem interface{}) bool {
xAsArray := reflect.ValueOf(x)
if xAsArray.Kind() == reflect.Slice {
for i := 0; i < xAsArray.Len(); i++ {
if xAsArray.Index(i).Interface() == elem {
return true
}
}
}
return false
}
// func ListComprehension(x interface{}, cond (interface{}) bool) bool {
// xAsArray := reflect.ValueOf(x)
// if xAsArray.Kind() == reflect.Slice {
// for i := 0; i < xAsArray.Len(); i++ {
// if xAsArray.Index(i).Interface() == elem {
// return true
// }
// }
// }
// return false
// }
/* ---------------------------------------------------------------- *
* METHOD array contains
* ---------------------------------------------------------------- */
func UniqueListOfStrings(X []string) []string {
var ok bool
m := map[string]bool{}
X_unique := []string{}
for _, x := range X {
if _, ok = m[x]; !ok {
X_unique = append(X_unique, x)
}
}
return X_unique
}
/* ---------------------------------------------------------------- *
* METHOD get value from array of unknown length
* ---------------------------------------------------------------- */
func GetArrayStringValue(arr *[]string, index int, Default string) string {
if arr != nil && len(*arr) > index {
return (*arr)[index]
}
return Default
}
func GetArrayBoolValue(arr *[]bool, index int, Default bool) bool {
if arr != nil && len(*arr) > index {
return (*arr)[index]
}
return Default
}
func GetArrayIntValue(arr *[]int, index int, Default int) int {
if arr != nil && len(*arr) > index {
return (*arr)[index]
}
return Default
}
func GetArrayInterfaceValue(arr *[](interface{}), index int, Default interface{}) interface{} {
if arr != nil && len(*arr) > index {
return (*arr)[index]
}
return Default
}

View File

@ -0,0 +1,96 @@
package utils
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"fmt"
"log"
"reflect"
"strconv"
"strings"
"github.com/lithammer/dedent"
"github.com/slongfield/pyfmt"
"ads/pkg/re"
)
/* ---------------------------------------------------------------- *
* METHOD format strings with dictionary substitution
* ---------------------------------------------------------------- */
func FormatPythonString(text string, arguments map[string]interface{}) string {
var (
err error
key string
value interface{}
kind reflect.Kind
refValue reflect.Value
)
// force compatibility of expressions with python
for key, value = range arguments {
kind = reflect.TypeOf(value).Kind()
switch kind {
case reflect.Ptr:
refValue = reflect.ValueOf(value)
if refValue.IsNil() {
arguments[key] = "None"
}
case reflect.Bool:
arguments[key] = strings.Title(fmt.Sprintf(`%v`, value))
}
}
text, err = pyfmt.Fmt(text, arguments)
if err != nil {
log.Fatal(err)
}
return text
}
/* ---------------------------------------------------------------- *
* METHOD dedent textblock and expand escaped symbols
* ---------------------------------------------------------------- */
func DedentIgnoreEmptyLines(text string) string {
return dedent.Dedent(text)
}
func DedentIgnoreFirstAndLast(text string) string {
text = re.Sub(`^\s*[\n\r]|[\n\r]\s*$`, ``, text)
return DedentIgnoreEmptyLines(text)
}
func DedentAndExpand(text string) string {
var err error
var result []string
result = []string{}
text = dedent.Dedent(text)
lines := strings.Split(text, "\n")
for _, line := range lines {
line = fmt.Sprintf(`"%s"`, line)
line, err = strconv.Unquote(line)
if err != nil {
log.Fatal(err)
}
result = append(result, line)
}
return strings.Join(result, "\n")
}
func FormatTextBlockAsList(text string, options ...bool) []string {
var unindent bool = GetArrayBoolValue(&options, 0, true)
if unindent {
text = DedentIgnoreFirstAndLast(text)
}
return re.Split(`\n`, text)
}
/* ---------------------------------------------------------------- *
* METHODS ansi
* ---------------------------------------------------------------- */
func StripAnsi(text string) string {
return re.Sub(`\x1b[^m]*m`, ``, text)
}

View File

@ -0,0 +1,34 @@
package endpoints
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"ads/internal/core/logging"
"ads/internal/setup"
)
/* ---------------------------------------------------------------- *
* ENDPOINT version
* ---------------------------------------------------------------- */
func Version() {
logging.SetForce(true)
logging.LogPlain(setup.Version())
}
/* ---------------------------------------------------------------- *
* ENDPOINT help
* ---------------------------------------------------------------- */
func Help() {
logging.SetForce(true)
logging.LogPlain(
"",
setup.Logo(),
// cli.Parser.Usage(nil),
setup.Help(),
"",
)
}

View File

@ -0,0 +1,20 @@
package endpoints
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"ads/internal/core/logging"
"ads/internal/setup"
)
/* ---------------------------------------------------------------- *
* ENDPOINT run
* ---------------------------------------------------------------- */
func Run(fnameConfig string) error {
logging.LogPlain(setup.Logo())
logging.LogWarn("Die Go-Implementierung ist noch unter Arbeit.")
return nil
}

View File

@ -0,0 +1,66 @@
package cli
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"github.com/akamensky/argparse"
"ads/internal/types"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES
* ---------------------------------------------------------------- */
var Parser *argparse.Parser
/* ---------------------------------------------------------------- *
* LOCAL VARIABLES / CONSTANTS
* ---------------------------------------------------------------- */
var optionsQuiet = argparse.Options{
Help: "Blendet alle Konsole-Messages aus.",
Required: false,
Default: false,
}
var optionsDebug = argparse.Options{
Help: "Blendet die Debugging-Befehle ein.",
Required: false,
Default: false,
}
var optionsColour = argparse.Options{
Help: "Ob Logging färblich angezeigt wird (default=true).",
Required: false,
// NOTE: no `Boolean` option available!
Default: "true",
}
var optionsConfigFile = argparse.Options{
Help: "Pfad zur Configdatei (nur für run Endpunkt).",
Required: false,
Default: "code/config.yml",
}
/* ---------------------------------------------------------------- *
* METHODS parse cli
* ---------------------------------------------------------------- */
func ParseCli(args []string) (*types.CliArguments, error) {
var err error
Parser = argparse.NewParser("cli parser", "Liest Optionen + Flags von Kommandozeile.")
arguments := types.CliArguments{
Help: Parser.NewCommand("help", ""),
Version: Parser.NewCommand("version", "Ruft Endpunkt auf, der die Version anzeigt."),
Run: Parser.NewCommand("run", "Ruft Endpunkt auf, der die Algorithmen laufen lässt."),
Quiet: Parser.Flag("q", "quiet", &optionsQuiet),
Debug: Parser.Flag("", "debug", &optionsDebug),
Colour: Parser.String("", "colour", &optionsColour),
ConfigFile: Parser.String("", "config", &optionsConfigFile),
}
err = Parser.Parse(args)
return &arguments, err
}

View File

@ -0,0 +1,56 @@
package setup
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"embed"
"fmt"
"log"
"strings"
"ads/internal/core/utils"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES
* ---------------------------------------------------------------- */
var Res embed.FS
var Assets map[string]string
/* ---------------------------------------------------------------- *
* METHOD read assets
* ---------------------------------------------------------------- */
func ReadAsset(key string) string {
var found bool
if _, found = Assets[key]; !found {
log.Fatal(fmt.Sprintf("Key \033[1m%s\033[0m not found in dictionary!", key))
}
data, err := Res.ReadFile(Assets[key])
if err != nil {
log.Fatal(err)
}
text := string(data)
return text
}
/* ---------------------------------------------------------------- *
* METHODS templates
* ---------------------------------------------------------------- */
func Help() string {
contents := ReadAsset("help")
return utils.DedentAndExpand(contents)
}
func Logo() string {
contents := ReadAsset("logo")
return utils.DedentAndExpand(contents)
}
func Version() string {
return strings.Trim(ReadAsset("version"), "\n")
}

View File

@ -0,0 +1,45 @@
package types
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"strings"
"github.com/akamensky/argparse"
"ads/pkg/re"
)
/* ---------------------------------------------------------------- *
* TYPES
* ---------------------------------------------------------------- */
type CliArguments struct {
Help *argparse.Command
Version *argparse.Command
Run *argparse.Command
Quiet *bool
Debug *bool
Colour *string
ConfigFile *string
}
/* ---------------------------------------------------------------- *
* METHODS convert string option to boolean
* ---------------------------------------------------------------- */
func IsTrue(text string) bool {
text = strings.TrimSpace(text)
return re.Matches(`(?i)(^(true|t|yes|y|1|\+|\+1)$)`, text)
}
func IsFalse(text string) bool {
text = strings.TrimSpace(text)
return re.Matches(`(?i)(^(false|f|no|n|0|-|-1)$)`, text)
}
func (arguments *CliArguments) ShowColour() bool {
return !IsFalse(*arguments.Colour)
}

68
code/golang/main.go Normal file
View File

@ -0,0 +1,68 @@
package main
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"embed"
"os"
"ads/internal/core/logging"
"ads/internal/endpoints"
"ads/internal/setup"
"ads/internal/setup/cli"
"ads/internal/types"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES
* ---------------------------------------------------------------- */
var (
// !!! NOTE: do not remove the following "comment", as it is a preprocessing instruction !!!
//go:embed assets/*
res embed.FS
assets = map[string]string{
"version": "assets/VERSION",
"logo": "assets/LOGO",
"help": "assets/HELP",
}
)
/* ---------------------------------------------------------------- *
* METHOD main
* ---------------------------------------------------------------- */
func main() {
var err error
var arguments *types.CliArguments
// set assets
setup.Res = res
setup.Assets = assets
// parse cli arguments
arguments, err = cli.ParseCli(os.Args)
// initialise logging options
if err == nil {
logging.SetQuietMode(*arguments.Quiet)
logging.SetDebugMode(*arguments.Debug)
logging.SetAnsiMode(arguments.ShowColour())
}
if err == nil {
if arguments.Version.Happened() {
endpoints.Version()
} else if arguments.Run.Happened() {
err = endpoints.Run(*arguments.ConfigFile)
} else { // } else if arguments.Help.Happened() {
endpoints.Help()
}
}
if err != nil {
logging.LogFatal(err)
}
}

62
code/golang/pkg/re/re.go Normal file
View File

@ -0,0 +1,62 @@
package re
/* ---------------------------------------------------------------- *
* IMPORTS
* ---------------------------------------------------------------- */
import (
"regexp"
)
/* ---------------------------------------------------------------- *
* GLOBAL VARIABLES
* ---------------------------------------------------------------- */
type Reader struct {
regex *regexp.Regexp
lastpattern *string
}
var defaultReader Reader = Reader{}
/* ---------------------------------------------------------------- *
* METHODS
* ---------------------------------------------------------------- */
func Matches(pattern string, text string) bool {
return defaultReader.Matches(pattern, text)
}
func Sub(pattern string, substitute string, text string) string {
return defaultReader.Sub(pattern, substitute, text)
}
func Split(pattern string, text string) []string {
return defaultReader.Split(pattern, text)
}
func (r *Reader) Matches(pattern string, text string) bool {
r.setReader(pattern)
return r.regex.MatchString(text)
}
func (r *Reader) Sub(pattern string, substitute string, text string) string {
r.setReader(pattern)
return r.regex.ReplaceAllString(text, substitute)
}
func (r *Reader) Split(pattern string, text string) []string {
r.setReader(pattern)
return r.regex.Split(text, -1)
}
/* ---------------------------------------------------------------- *
* PRIVATE MEHODS
* ---------------------------------------------------------------- */
func (r *Reader) setReader(pattern string) {
if r.regex == nil || r.lastpattern == nil || *r.lastpattern != pattern {
r.lastpattern = &pattern
r.regex = regexp.MustCompile(pattern)
}
}

6
code/golang/requirements Normal file
View File

@ -0,0 +1,6 @@
github.com/akamensky/argparse@v1.3.1
github.com/lithammer/dedent@v1.1.0
github.com/slongfield/pyfmt@v0.0.0-20180124071345-020a7cb18bca
github.com/stretchr/testify@v1.7.0
golang.org/x/tools
gopkg.in/yaml.v3@v3.0.0-20210107192922-496545a6307b