]> 91.132.146.200 Git - scientia.git/commitdiff
a go cli and tui client. Not really ready yet
authorBanana <mail@bananas-playground.net>
Sun, 8 Jan 2023 00:02:42 +0000 (01:02 +0100)
committerBanana <mail@bananas-playground.net>
Sun, 8 Jan 2023 00:02:42 +0000 (01:02 +0100)
15 files changed:
client/go-cli/README [new file with mode: 0644]
client/go-cli/scientia-cli.go [new file with mode: 0644]
client/go-client/README [deleted file]
client/go-client/_scientia.go [deleted file]
client/go-client/go.mod [deleted file]
client/go-client/go.sum [deleted file]
client/go-client/scientia [deleted file]
client/go-client/scientia.go [deleted file]
client/go-tui/README [new file with mode: 0644]
client/go-tui/TODO [new file with mode: 0644]
client/go-tui/create.go [new file with mode: 0644]
client/go-tui/go.mod [new file with mode: 0644]
client/go-tui/go.sum [new file with mode: 0644]
client/go-tui/scientia-tui.go [new file with mode: 0644]
client/go-tui/start.go [new file with mode: 0644]

diff --git a/client/go-cli/README b/client/go-cli/README
new file mode 100644 (file)
index 0000000..f3f6d65
--- /dev/null
@@ -0,0 +1,9 @@
+This is a terminal cli client written in go to be used with scientia
+https://://www.bananas-playground.net/projekt/scientia
+
+!WARNING!
+This is a very simple, with limited experience written, go program.
+Use at own risk and feel free to improve.
+
+Howto build:
+Nothing special, just go build -o scientia-cli
diff --git a/client/go-cli/scientia-cli.go b/client/go-cli/scientia-cli.go
new file mode 100644 (file)
index 0000000..9ce1858
--- /dev/null
@@ -0,0 +1,254 @@
+package main
+
+import (
+       "errors"
+       "fmt"
+       "log"
+       "math/rand"
+       "os"
+       "flag"
+       "gopkg.in/yaml.v2"
+       "net/http"
+       "io/ioutil"
+       "bytes"
+       "mime/multipart"
+       "encoding/json"
+)
+
+/**
+ * scientia
+ *
+ * Copyright 2022 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
+ *
+ * You should have received a copy of the
+ * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
+ */
+
+const website = "https://www.bananas-playground.net/projekt/scientia"
+const version = "1.0"
+// used for non-existing default config
+const letters = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
+
+// command line parameters
+var optsVerbose bool
+var optsCreateConfig bool
+var optsDebug bool
+
+// config
+var cfg Config
+// config file struct
+type Config struct {
+       Endpoint struct {
+               Host string `yaml:"host"`
+               Secret string `yaml:"secret"`
+       } `yaml:"endpoint"`
+}
+
+// response json struct
+type Response struct {
+       Message string `json:"message"`
+       Status int `json:"status"`
+}
+
+/**
+ * Main
+ */
+func main() {
+
+       // parse commandline parameters
+       flag.BoolVar(&optsVerbose, "verbose", false, "Produce verbose output")
+       flag.BoolVar(&optsCreateConfig, "create-config-file", false, "Create default config file")
+       flag.BoolVar(&optsDebug, "debug", false, "Print debug infos")
+       flag.Parse()
+       if optsDebug {
+               fmt.Println("verbose:", optsVerbose)
+               fmt.Println("create-config-file:", optsCreateConfig)
+               fmt.Println("debug:", optsDebug)
+       }
+
+       // load the config and populate Config
+       loadConfig()
+
+       // get the payload
+       payload := getInput()
+       if optsDebug { log.Println(payload) }
+
+       // do the upload and get the response
+       responseString := uploadCall(payload)
+       response := Response{}
+       json.Unmarshal([]byte(responseString), &response)
+
+       // print the result and link to the pasty
+       fmt.Printf("Status: %d\n", response.Status)
+       fmt.Printf("Message: %s\n", response.Message)
+}
+
+
+
+
+/**
+ * Check and display error with additional message
+ */
+func errorCheck(e error, msg string) {
+       if e != nil {
+               log.Fatal(msg,e)
+       }
+}
+
+/**
+ * just a random string
+ */
+func randStringBytes(n int) string {
+       b := make([]byte, n)
+       for i := range b {
+               b[i] = letters[rand.Intn(len(letters))]
+       }
+       return string(b)
+}
+
+/**
+ * load or even create a default config
+ * $HOME/.scientia.yaml
+ */
+func loadConfig() {
+       homeDir, err := os.UserHomeDir()
+       errorCheck(err, "No $HOME directory available?")
+       if optsVerbose { log.Printf("Your $HOME: %s \n", homeDir) }
+
+       var configFile = homeDir + "/.scientia.yaml"
+
+       if _, err := os.Stat(configFile); errors.Is(err, os.ErrNotExist) {
+               log.Printf("Config file not found: %s \n", configFile)
+
+               if optsCreateConfig {
+                       log.Printf("Creating new default config file: %s \n", configFile)
+
+                       newConfig, err := os.Create(configFile)
+                       errorCheck(err, "Can not create config file!")
+                       defer newConfig.Close()
+
+
+                       _, err = fmt.Fprintf(newConfig, "# scientia go client config file.\n")
+                       errorCheck(err, "Can not write to new config file")
+                       fmt.Fprintf(newConfig, "# See %s for more details.\n", website)
+                       fmt.Fprintf(newConfig, "# Version: %s\n", version)
+                       fmt.Fprintf(newConfig, "endpoint:\n")
+                       fmt.Fprintf(newConfig, "  host: http://your-scientia-endpoi.nt\n")
+                       fmt.Fprintf(newConfig, "  secret: %s\n", randStringBytes(50))
+
+                       log.Fatalf("New default config file created: - %s - Edit and launch again!",configFile)
+               }
+       }
+
+       existingConfigFile, err := os.Open(configFile)
+       errorCheck(err, "Can not open config file")
+       defer existingConfigFile.Close()
+       if optsVerbose { log.Printf("Reading config file: %s \n", configFile) }
+
+       var decoder = yaml.NewDecoder(existingConfigFile)
+       err = decoder.Decode(&cfg)
+       errorCheck(err, "Can not decode config file")
+
+       if cfg.Endpoint.Host == "" || cfg.Endpoint.Secret == "" {
+               log.Fatal("Empty config?")
+       }
+
+       if optsDebug {
+               log.Println(cfg.Endpoint.Host)
+               log.Println(cfg.Endpoint.Secret)
+       }
+}
+
+/**
+ * Do a http POST call to the defined endpoint
+ * and upload the payload
+ * Return response body as string
+ */
+func uploadCall(payload string) string {
+
+       if optsVerbose { log.Println("Starting to upload data") }
+       if optsDebug { log.Println(payload) }
+       if len(payload) == 0 {
+               log.Fatal("Nothing provided to upload")
+       }
+
+       // Buffer to store our request body as bytes
+       var requestBody bytes.Buffer
+
+       // Create a multipart writer
+       multiPartWriter := multipart.NewWriter(&requestBody)
+
+       // file field
+       fileWriter, err := multiPartWriter.CreateFormFile("pasty", "pastyfile")
+       errorCheck(err, "Can not create form file field")
+       fileWriter.Write([]byte(payload))
+
+       dlField, err := multiPartWriter.CreateFormField("dl")
+       errorCheck(err, "Can not create form dl field")
+       dlField.Write([]byte(cfg.Endpoint.Secret))
+
+       multiPartWriter.Close()
+
+       req, err := http.NewRequest(http.MethodPost, cfg.Endpoint.Host, &requestBody)
+       errorCheck(err, "Can not create http request")
+       // We need to set the content type from the writer, it includes necessary boundary as well
+       req.Header.Set("Content-Type", multiPartWriter.FormDataContentType())
+       req.Header.Set("User-Agent", "scientiaAgent/1.0");
+
+       // Do the request
+       client := &http.Client{}
+       response, err := client.Do(req)
+       errorCheck(err, "POST request failed")
+
+       responseBody, err := ioutil.ReadAll(response.Body)
+       errorCheck(err, "Can not read response body")
+
+       if optsVerbose { log.Println("Request done") }
+       if optsDebug {
+               log.Printf("Response status code: %d\n",response.StatusCode)
+               log.Printf("Response headers: %#v\n", response.Header)
+               log.Println(string(responseBody))
+       }
+
+       return string(responseBody)
+}
+
+/**
+ * check if file is provided as commandline argument
+ * or piped into
+ * return the read data as string
+ */
+func getInput() string {
+       if optsVerbose { log.Println("Getting input") }
+
+       var inputString string
+
+       if filename := flag.Arg(0); filename != "" {
+               if optsVerbose { log.Println("Read from file argument") }
+
+               bytes, err := os.ReadFile(filename)
+               errorCheck(err, "Error opening file")
+               inputString = string(bytes)
+       } else {
+               stat, _ := os.Stdin.Stat()
+               if (stat.Mode() & os.ModeCharDevice) == 0 {
+                       if optsVerbose { log.Println("data is being piped") }
+
+                       bytes, _ := ioutil.ReadAll(os.Stdin)
+                       inputString = string(bytes)
+               }
+       }
+
+       if len(inputString) == 0 {
+               log.Fatal("Nothing provided to upload")
+       }
+
+       return inputString
+}
diff --git a/client/go-client/README b/client/go-client/README
deleted file mode 100644 (file)
index 7c64d47..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a client written in go to be used with scientia
-https://://www.bananas-playground.net/projekt/scientia
-
-!WARNING!
-This is a very simple, with limited experience written, go program.
-Use at own risk and feel free to improve.
-
-Howto build:
-Nothing special, just go build -o scientia 
\ No newline at end of file
diff --git a/client/go-client/_scientia.go b/client/go-client/_scientia.go
deleted file mode 100644 (file)
index 9ce1858..0000000
+++ /dev/null
@@ -1,254 +0,0 @@
-package main
-
-import (
-       "errors"
-       "fmt"
-       "log"
-       "math/rand"
-       "os"
-       "flag"
-       "gopkg.in/yaml.v2"
-       "net/http"
-       "io/ioutil"
-       "bytes"
-       "mime/multipart"
-       "encoding/json"
-)
-
-/**
- * scientia
- *
- * Copyright 2022 Johannes Keßler
- *
- * https://www.bananas-playground.net/projekt/scientia/
- *
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
- *
- * You should have received a copy of the
- * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
- * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
- */
-
-const website = "https://www.bananas-playground.net/projekt/scientia"
-const version = "1.0"
-// used for non-existing default config
-const letters = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-_"
-
-// command line parameters
-var optsVerbose bool
-var optsCreateConfig bool
-var optsDebug bool
-
-// config
-var cfg Config
-// config file struct
-type Config struct {
-       Endpoint struct {
-               Host string `yaml:"host"`
-               Secret string `yaml:"secret"`
-       } `yaml:"endpoint"`
-}
-
-// response json struct
-type Response struct {
-       Message string `json:"message"`
-       Status int `json:"status"`
-}
-
-/**
- * Main
- */
-func main() {
-
-       // parse commandline parameters
-       flag.BoolVar(&optsVerbose, "verbose", false, "Produce verbose output")
-       flag.BoolVar(&optsCreateConfig, "create-config-file", false, "Create default config file")
-       flag.BoolVar(&optsDebug, "debug", false, "Print debug infos")
-       flag.Parse()
-       if optsDebug {
-               fmt.Println("verbose:", optsVerbose)
-               fmt.Println("create-config-file:", optsCreateConfig)
-               fmt.Println("debug:", optsDebug)
-       }
-
-       // load the config and populate Config
-       loadConfig()
-
-       // get the payload
-       payload := getInput()
-       if optsDebug { log.Println(payload) }
-
-       // do the upload and get the response
-       responseString := uploadCall(payload)
-       response := Response{}
-       json.Unmarshal([]byte(responseString), &response)
-
-       // print the result and link to the pasty
-       fmt.Printf("Status: %d\n", response.Status)
-       fmt.Printf("Message: %s\n", response.Message)
-}
-
-
-
-
-/**
- * Check and display error with additional message
- */
-func errorCheck(e error, msg string) {
-       if e != nil {
-               log.Fatal(msg,e)
-       }
-}
-
-/**
- * just a random string
- */
-func randStringBytes(n int) string {
-       b := make([]byte, n)
-       for i := range b {
-               b[i] = letters[rand.Intn(len(letters))]
-       }
-       return string(b)
-}
-
-/**
- * load or even create a default config
- * $HOME/.scientia.yaml
- */
-func loadConfig() {
-       homeDir, err := os.UserHomeDir()
-       errorCheck(err, "No $HOME directory available?")
-       if optsVerbose { log.Printf("Your $HOME: %s \n", homeDir) }
-
-       var configFile = homeDir + "/.scientia.yaml"
-
-       if _, err := os.Stat(configFile); errors.Is(err, os.ErrNotExist) {
-               log.Printf("Config file not found: %s \n", configFile)
-
-               if optsCreateConfig {
-                       log.Printf("Creating new default config file: %s \n", configFile)
-
-                       newConfig, err := os.Create(configFile)
-                       errorCheck(err, "Can not create config file!")
-                       defer newConfig.Close()
-
-
-                       _, err = fmt.Fprintf(newConfig, "# scientia go client config file.\n")
-                       errorCheck(err, "Can not write to new config file")
-                       fmt.Fprintf(newConfig, "# See %s for more details.\n", website)
-                       fmt.Fprintf(newConfig, "# Version: %s\n", version)
-                       fmt.Fprintf(newConfig, "endpoint:\n")
-                       fmt.Fprintf(newConfig, "  host: http://your-scientia-endpoi.nt\n")
-                       fmt.Fprintf(newConfig, "  secret: %s\n", randStringBytes(50))
-
-                       log.Fatalf("New default config file created: - %s - Edit and launch again!",configFile)
-               }
-       }
-
-       existingConfigFile, err := os.Open(configFile)
-       errorCheck(err, "Can not open config file")
-       defer existingConfigFile.Close()
-       if optsVerbose { log.Printf("Reading config file: %s \n", configFile) }
-
-       var decoder = yaml.NewDecoder(existingConfigFile)
-       err = decoder.Decode(&cfg)
-       errorCheck(err, "Can not decode config file")
-
-       if cfg.Endpoint.Host == "" || cfg.Endpoint.Secret == "" {
-               log.Fatal("Empty config?")
-       }
-
-       if optsDebug {
-               log.Println(cfg.Endpoint.Host)
-               log.Println(cfg.Endpoint.Secret)
-       }
-}
-
-/**
- * Do a http POST call to the defined endpoint
- * and upload the payload
- * Return response body as string
- */
-func uploadCall(payload string) string {
-
-       if optsVerbose { log.Println("Starting to upload data") }
-       if optsDebug { log.Println(payload) }
-       if len(payload) == 0 {
-               log.Fatal("Nothing provided to upload")
-       }
-
-       // Buffer to store our request body as bytes
-       var requestBody bytes.Buffer
-
-       // Create a multipart writer
-       multiPartWriter := multipart.NewWriter(&requestBody)
-
-       // file field
-       fileWriter, err := multiPartWriter.CreateFormFile("pasty", "pastyfile")
-       errorCheck(err, "Can not create form file field")
-       fileWriter.Write([]byte(payload))
-
-       dlField, err := multiPartWriter.CreateFormField("dl")
-       errorCheck(err, "Can not create form dl field")
-       dlField.Write([]byte(cfg.Endpoint.Secret))
-
-       multiPartWriter.Close()
-
-       req, err := http.NewRequest(http.MethodPost, cfg.Endpoint.Host, &requestBody)
-       errorCheck(err, "Can not create http request")
-       // We need to set the content type from the writer, it includes necessary boundary as well
-       req.Header.Set("Content-Type", multiPartWriter.FormDataContentType())
-       req.Header.Set("User-Agent", "scientiaAgent/1.0");
-
-       // Do the request
-       client := &http.Client{}
-       response, err := client.Do(req)
-       errorCheck(err, "POST request failed")
-
-       responseBody, err := ioutil.ReadAll(response.Body)
-       errorCheck(err, "Can not read response body")
-
-       if optsVerbose { log.Println("Request done") }
-       if optsDebug {
-               log.Printf("Response status code: %d\n",response.StatusCode)
-               log.Printf("Response headers: %#v\n", response.Header)
-               log.Println(string(responseBody))
-       }
-
-       return string(responseBody)
-}
-
-/**
- * check if file is provided as commandline argument
- * or piped into
- * return the read data as string
- */
-func getInput() string {
-       if optsVerbose { log.Println("Getting input") }
-
-       var inputString string
-
-       if filename := flag.Arg(0); filename != "" {
-               if optsVerbose { log.Println("Read from file argument") }
-
-               bytes, err := os.ReadFile(filename)
-               errorCheck(err, "Error opening file")
-               inputString = string(bytes)
-       } else {
-               stat, _ := os.Stdin.Stat()
-               if (stat.Mode() & os.ModeCharDevice) == 0 {
-                       if optsVerbose { log.Println("data is being piped") }
-
-                       bytes, _ := ioutil.ReadAll(os.Stdin)
-                       inputString = string(bytes)
-               }
-       }
-
-       if len(inputString) == 0 {
-               log.Fatal("Nothing provided to upload")
-       }
-
-       return inputString
-}
diff --git a/client/go-client/go.mod b/client/go-client/go.mod
deleted file mode 100644 (file)
index bd776c7..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-module scientia/go-client
-
-go 1.19
-
-require (
-       github.com/charmbracelet/bubbles v0.14.0
-       github.com/charmbracelet/bubbletea v0.23.1
-       github.com/charmbracelet/lipgloss v0.6.0
-)
-
-require (
-       github.com/atotto/clipboard v0.1.4 // indirect
-       github.com/aymanbagabas/go-osc52 v1.0.3 // indirect
-       github.com/containerd/console v1.0.3 // indirect
-       github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
-       github.com/mattn/go-isatty v0.0.16 // indirect
-       github.com/mattn/go-localereader v0.0.1 // indirect
-       github.com/mattn/go-runewidth v0.0.14 // indirect
-       github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect
-       github.com/muesli/cancelreader v0.2.2 // indirect
-       github.com/muesli/reflow v0.3.0 // indirect
-       github.com/muesli/termenv v0.13.0 // indirect
-       github.com/rivo/uniseg v0.2.0 // indirect
-       github.com/sahilm/fuzzy v0.1.0 // indirect
-       golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
-       golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
-       golang.org/x/text v0.3.7 // indirect
-)
diff --git a/client/go-client/go.sum b/client/go-client/go.sum
deleted file mode 100644 (file)
index 45ebbf2..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
-github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
-github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
-github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
-github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og=
-github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
-github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=
-github.com/charmbracelet/bubbletea v0.23.1 h1:CYdteX1wCiCzKNUlwm25ZHBIc1GXlYFyUIte8WPvhck=
-github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU=
-github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
-github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=
-github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY=
-github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk=
-github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
-github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
-github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
-github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
-github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
-github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
-github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
-github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
-github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
-github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
-github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
-github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34=
-github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
-github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
-github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
-github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
-github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
-github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
-github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
-github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
-github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
-github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
-github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
-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/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
-github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/client/go-client/scientia b/client/go-client/scientia
deleted file mode 100755 (executable)
index 2eacc3a..0000000
Binary files a/client/go-client/scientia and /dev/null differ
diff --git a/client/go-client/scientia.go b/client/go-client/scientia.go
deleted file mode 100644 (file)
index fc60015..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-package main
-
-import (
-       "fmt"
-       "io"
-       "os"
-
-       "github.com/charmbracelet/bubbles/list"
-       tea "github.com/charmbracelet/bubbletea"
-       "github.com/charmbracelet/lipgloss"
-)
-
-const listHeight = 14
-
-var (
-       titleStyle = lipgloss.NewStyle().MarginLeft(2)
-       itemStyle = lipgloss.NewStyle().PaddingLeft(4)
-       selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
-       paginationStyle  = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
-       helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)
-       quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 2, 4)
-)
-
-type item string
-
-func (i item) FilterValue() string { return "" }
-
-type itemDelegate struct{}
-
-func (d itemDelegate) Height() int                               { return 1 }
-func (d itemDelegate) Spacing() int                              { return 0 }
-func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd { return nil }
-
-func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
-       i, ok := listItem.(item)
-       if !ok {
-               return
-       }
-
-       str := fmt.Sprintf("%d. %s", index+1, i)
-
-       fn := itemStyle.Render
-       if index == m.Index() {
-               fn = func(s string) string {
-                       return selectedItemStyle.Render("> " + s)
-               }
-       }
-
-       fmt.Fprint(w, fn(str))
-}
-
-type model struct {
-       list list.Model
-       choice string
-       quitting bool
-}
-
-func (m model) Init() tea.Cmd {
-       return nil
-}
-
-func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
-       switch msg := msg.(type) {
-               case tea.WindowSizeMsg:
-                       m.list.SetWidth(msg.Width)
-                       return m, nil
-
-               case tea.KeyMsg:
-                       switch keypress := msg.String(); keypress {
-                               case "ctrl+c":
-                                       m.quitting = true
-                                       return m, tea.Quit
-
-                               case "enter":
-                                       i, ok := m.list.SelectedItem().(item)
-                                       if ok {
-                                               m.choice = string(i)
-                                       }
-                                       return m, tea.Quit
-                               }
-       }
-
-       var cmd tea.Cmd
-       m.list, cmd = m.list.Update(msg)
-       return m, cmd
-}
-
-func (m model) View() string {
-       if m.choice != "" {
-               return quitTextStyle.Render(fmt.Sprintf("%s? Sounds good to me.", m.choice))
-       }
-       if m.quitting {
-               return quitTextStyle.Render("Not hungry? That’s cool.")
-       }
-       return "\n" + m.list.View()
-}
-
-func main() {
-       items := []list.Item{
-               item("Ramen"),
-               item("Tomato Soup"),
-               item("Hamburgers"),
-               item("Cheeseburgers"),
-               item("Currywurst"),
-               item("Okonomiyaki"),
-               item("Pasta"),
-               item("Fillet Mignon"),
-               item("Caviar"),
-               item("Just Wine"),
-       }
-
-       const defaultWidth = 20
-
-       l := list.New(items, itemDelegate{}, defaultWidth, listHeight)
-       l.Title = "What do you want for dinner?"
-       l.SetShowStatusBar(false)
-       l.SetFilteringEnabled(false)
-       l.Styles.Title = titleStyle
-       l.Styles.PaginationStyle = paginationStyle
-       l.Styles.HelpStyle = helpStyle
-
-       m := model{list: l}
-
-       if _, err := tea.NewProgram(m).Run(); err != nil {
-               fmt.Println("Error running program:", err)
-               os.Exit(1)
-       }
-}
\ No newline at end of file
diff --git a/client/go-tui/README b/client/go-tui/README
new file mode 100644 (file)
index 0000000..3c22350
--- /dev/null
@@ -0,0 +1,9 @@
+This is a terminal tui client written in go to be used with scientia
+https://://www.bananas-playground.net/projekt/scientia
+
+!WARNING!
+This is a very simple, with limited experience written, go program.
+Use at own risk and feel free to improve.
+
+Howto build:
+Nothing special, just go build -o scientia-tui
diff --git a/client/go-tui/TODO b/client/go-tui/TODO
new file mode 100644 (file)
index 0000000..e9f8f34
--- /dev/null
@@ -0,0 +1 @@
+Reset the create input field. Not sure where yet.
diff --git a/client/go-tui/create.go b/client/go-tui/create.go
new file mode 100644 (file)
index 0000000..ae5c8c9
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * scientia
+ *
+ * A terminal client written in go.
+ *
+ * Copyright 2023 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
+ *
+ * You should have received a copy of the
+ * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
+ *
+ *
+ * This is the create "screen". It displays a textarea to input text into.
+ * Does the save and creation
+ */
+package main
+
+import (
+       "github.com/charmbracelet/bubbles/textarea"
+       tea "github.com/charmbracelet/bubbletea"
+       "github.com/charmbracelet/lipgloss"
+)
+
+var (
+       headline = lipgloss.NewStyle().Margin(1, 0, 1, 2)
+       infoText = lipgloss.NewStyle().Margin(1, 0, 1, 2).Foreground(lipgloss.AdaptiveColor{Light: "#969B86", Dark: "#696969"})
+)
+
+func initCreate() textarea.Model {
+       ta := textarea.New()
+       ta.Placeholder = "Once upon a time..."
+       ta.SetHeight(10)
+       ta.SetWidth(50)
+       ta.Focus()
+
+       return ta
+}
+
+func createView(m mainModel) string {
+       return lipgloss.JoinVertical(lipgloss.Left,
+               headline.Render("Create a new entry"), m.create.View(),
+               infoText.Render("esc*2 to get back and discard. ctrl+s to save."))
+}
+
+func createUpdate(msg tea.Msg, m mainModel) (tea.Model, tea.Cmd) {
+
+       var cmds []tea.Cmd
+       var cmd tea.Cmd
+
+       switch msg := msg.(type) {
+
+               case tea.KeyMsg:
+                       switch msg.Type {
+                               case tea.KeyCtrlC:
+                                       m.quitting = true
+                                       return m, tea.Quit
+                               case tea.KeyCtrlS:
+                                       m.choice = ""
+                                       return m, nil
+
+                               case tea.KeyEsc:
+                                       if m.create.Focused() {
+                                               m.create.Blur()
+                                       } else if !m.create.Focused() {
+                                               m.choice = ""
+                                               return m, nil
+                                       }
+                               default:
+                                       if !m.create.Focused() {
+                                               cmd = m.create.Focus()
+                                               cmds = append(cmds, cmd)
+                                       }
+                               }
+       }
+
+       m.create, cmd = m.create.Update(msg)
+       cmds = append(cmds, cmd)
+       return m, tea.Batch(cmds...)
+}
diff --git a/client/go-tui/go.mod b/client/go-tui/go.mod
new file mode 100644 (file)
index 0000000..479490f
--- /dev/null
@@ -0,0 +1,28 @@
+module scientia/go-client
+
+go 1.19
+
+require (
+       github.com/charmbracelet/bubbles v0.14.0
+       github.com/charmbracelet/bubbletea v0.23.1
+       github.com/charmbracelet/lipgloss v0.6.0
+)
+
+require (
+       github.com/atotto/clipboard v0.1.4 // indirect
+       github.com/aymanbagabas/go-osc52 v1.2.1 // indirect
+       github.com/containerd/console v1.0.3 // indirect
+       github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
+       github.com/mattn/go-isatty v0.0.17 // indirect
+       github.com/mattn/go-localereader v0.0.1 // indirect
+       github.com/mattn/go-runewidth v0.0.14 // indirect
+       github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a // indirect
+       github.com/muesli/cancelreader v0.2.2 // indirect
+       github.com/muesli/reflow v0.3.0 // indirect
+       github.com/muesli/termenv v0.13.0 // indirect
+       github.com/rivo/uniseg v0.4.3 // indirect
+       github.com/sahilm/fuzzy v0.1.0 // indirect
+       golang.org/x/sys v0.4.0 // indirect
+       golang.org/x/term v0.4.0 // indirect
+       golang.org/x/text v0.6.0 // indirect
+)
diff --git a/client/go-tui/go.sum b/client/go-tui/go.sum
new file mode 100644 (file)
index 0000000..eb1c470
--- /dev/null
@@ -0,0 +1,72 @@
+github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
+github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
+github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg=
+github.com/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
+github.com/aymanbagabas/go-osc52 v1.2.1 h1:q2sWUyDcozPLcLabEMd+a+7Ea2DitxZVN9hTxab9L4E=
+github.com/aymanbagabas/go-osc52 v1.2.1/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4=
+github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og=
+github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc=
+github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4=
+github.com/charmbracelet/bubbletea v0.23.1 h1:CYdteX1wCiCzKNUlwm25ZHBIc1GXlYFyUIte8WPvhck=
+github.com/charmbracelet/bubbletea v0.23.1/go.mod h1:JAfGK/3/pPKHTnAS8JIE2u9f61BjWTQY57RbT25aMXU=
+github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
+github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs=
+github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY=
+github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk=
+github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
+github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
+github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
+github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
+github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
+github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
+github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
+github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88=
+github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
+github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
+github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
+github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34=
+github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
+github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a h1:jlDOeO5TU0pYlbc/y6PFguab5IjANI0Knrpg3u/ton4=
+github.com/muesli/ansi v0.0.0-20221106050444-61f0cd9a192a/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo=
+github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
+github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
+github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo=
+github.com/muesli/reflow v0.2.1-0.20210115123740-9e1d0d53df68/go.mod h1:Xk+z4oIWdQqJzsxyjgl3P22oYZnHdZ8FFTHAQQt5BMQ=
+github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s=
+github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8=
+github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
+github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs=
+github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
+github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
+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/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw=
+github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
+github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI=
+github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
+golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab h1:2QkjZIsXupsJbJIdSjjUOgWK3aEtzyuh2mPt3l/CkeU=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
+golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
+golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
+golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
+golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
diff --git a/client/go-tui/scientia-tui.go b/client/go-tui/scientia-tui.go
new file mode 100644 (file)
index 0000000..8864044
--- /dev/null
@@ -0,0 +1,94 @@
+/**
+ * scientia
+ *
+ * A terminal client written in go.
+ *
+ * Copyright 2023 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
+ *
+ * You should have received a copy of the
+ * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
+ */
+package main
+
+import (
+       "fmt"
+       "github.com/charmbracelet/bubbles/textarea"
+       "github.com/charmbracelet/lipgloss"
+       "os"
+
+       "github.com/charmbracelet/bubbles/list"
+       tea "github.com/charmbracelet/bubbletea"
+)
+
+// the unique identifiers for each action of the initial list of actions
+const (
+       ITEM_CREATE_VALUE = "create"
+       ITEM_LIST_VALUE = "list"
+       ITEM_UPDATE_VALUE = "update"
+)
+
+// some global vars
+var (
+       quitTextStyle = lipgloss.NewStyle().Margin(1, 0, 1, 2)
+)
+
+// mainModel Holds all the important stuff
+// Needs to be extended if a new action is added
+type mainModel struct {
+       start list.Model
+       create textarea.Model
+       choice string
+       quitting bool
+}
+
+func (m mainModel) Init() tea.Cmd {
+       return nil
+}
+
+// Update The main Update method. Decides the correct action update method
+func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
+       switch m.choice {
+               case ITEM_UPDATE_VALUE:
+                       //return quitTextStyle.Render("Update it is")
+               case ITEM_LIST_VALUE:
+                       //return quitTextStyle.Render("List it is")
+               case ITEM_CREATE_VALUE:
+                       return createUpdate(msg, m)
+       }
+       return startUpdate(msg, m)
+}
+
+// View The main View method. Decides which action view is called
+func (m mainModel) View() string {
+       if m.quitting {
+               return quitTextStyle.Render("Good day.")
+       }
+
+       switch m.choice {
+               case ITEM_UPDATE_VALUE:
+                       return quitTextStyle.Render("Update it is")
+               case ITEM_LIST_VALUE:
+                       return quitTextStyle.Render("List it is")
+               case ITEM_CREATE_VALUE:
+                       return createView(m)
+       }
+
+       return startView(m)
+}
+
+func main() {
+       m := mainModel{start: initStart(), create: initCreate()}
+       p := tea.NewProgram(m)
+
+       if err := p.Start(); err != nil {
+               fmt.Println("Error running program:", err)
+               os.Exit(1)
+       }
+}
diff --git a/client/go-tui/start.go b/client/go-tui/start.go
new file mode 100644 (file)
index 0000000..043c219
--- /dev/null
@@ -0,0 +1,134 @@
+/**
+ * scientia
+ *
+ * A terminal client written in go.
+ *
+ * Copyright 2023 Johannes Keßler
+ *
+ * https://www.bananas-playground.net/projekt/scientia/
+ *
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the COMMON DEVELOPMENT AND DISTRIBUTION LICENSE
+ *
+ * You should have received a copy of the
+ * COMMON DEVELOPMENT AND DISTRIBUTION LICENSE (CDDL) Version 1.0
+ * along with this program.  If not, see http://www.sun.com/cddl/cddl.html
+ *
+ *
+ * This is the start "screen" which displays the available actions which can be selected.
+ * The values and identifiers are defined in the main file, since they are used there too
+ */
+package main
+
+import (
+       "fmt"
+       "github.com/charmbracelet/bubbles/list"
+       tea "github.com/charmbracelet/bubbletea"
+       "github.com/charmbracelet/lipgloss"
+       "io"
+)
+
+var (
+       titleStyle        = lipgloss.NewStyle().MarginLeft(0)
+       itemStyle         = lipgloss.NewStyle().PaddingLeft(4)
+       selectedItemStyle = lipgloss.NewStyle().PaddingLeft(2).Foreground(lipgloss.Color("170"))
+       paginationStyle   = list.DefaultStyles().PaginationStyle.PaddingLeft(4)
+       helpStyle         = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1)
+)
+
+
+// item stuff
+type item struct {
+       title, desc string
+}
+func (i item) Title() string       { return i.title }
+func (i item) Description() string { return i.desc }
+func (i item) FilterValue() string { return i.title }
+
+type itemDelegate struct{}
+
+func (d itemDelegate) Height() int {
+       return 1
+}
+func (d itemDelegate) Spacing() int {
+       return 0
+}
+func (d itemDelegate) Update(msg tea.Msg, m *list.Model) tea.Cmd {
+       return nil
+}
+func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) {
+       i, ok := listItem.(item)
+       if !ok {
+               return
+       }
+
+       str := fmt.Sprintf("%d. %s", index+1, i.Title())
+
+       fn := itemStyle.Render
+       if index == m.Index() {
+               fn = func(s string) string {
+                       return selectedItemStyle.Render("> " + s)
+               }
+       }
+
+       fmt.Fprint(w, fn(str))
+}
+
+func initStart() list.Model {
+       items := []list.Item {
+               item{title: "Create", desc: ITEM_CREATE_VALUE},
+               item{title: "List", desc: ITEM_LIST_VALUE},
+               item{title: "Update", desc: ITEM_UPDATE_VALUE},
+       }
+
+       l := list.New(items, itemDelegate{}, 20, 14)
+       l.Title = "Please select an option"
+       l.SetShowStatusBar(false)
+       l.SetFilteringEnabled(false)
+       l.Styles.Title = titleStyle
+       l.Styles.PaginationStyle = paginationStyle
+       l.Styles.HelpStyle = helpStyle
+
+       return l
+}
+
+func startView(m mainModel) string {
+       return fmt.Sprintf("\n%s", m.start.View())
+}
+
+func startUpdate(msg tea.Msg, m mainModel) (tea.Model, tea.Cmd) {
+       switch msg := msg.(type) {
+       case tea.WindowSizeMsg:
+               m.start.SetWidth(msg.Width)
+               return m, nil
+
+       case tea.KeyMsg:
+               switch msg.Type {
+                       // esc does close?
+                       case tea.KeyEsc:
+                               return m, nil
+                       case tea.KeyCtrlC:
+                               m.quitting = true
+                               return m, tea.Quit
+
+                       case tea.KeyEnter:
+                               i, ok := m.start.SelectedItem().(item)
+                               if ok {
+                                       m.choice = i.Description()
+                               }
+                               return m, nil
+
+                       case tea.KeyRunes:
+                               switch string(msg.Runes) {
+                                       case "q":
+                                               m.quitting = true
+                                               return m, tea.Quit
+                                       }
+                       }
+       }
+
+       var cmd tea.Cmd
+       m.start, cmd = m.start.Update(msg)
+       return m, cmd
+}