Add update session command
This commit is contained in:
parent
2c854d4f8b
commit
be95c23d5f
15 changed files with 710 additions and 115 deletions
|
@ -33,7 +33,6 @@ func init() {
|
||||||
// and all subcommands, e.g.:
|
// and all subcommands, e.g.:
|
||||||
|
|
||||||
createCmd.PersistentFlags().StringP("input", "i", "", "Specify an input file")
|
createCmd.PersistentFlags().StringP("input", "i", "", "Specify an input file")
|
||||||
createCmd.PersistentFlags().Bool("stdin", false, "Consume a string from stdin")
|
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
// Cobra supports local flags which will only run when this command
|
||||||
// is called directly, e.g.:
|
// is called directly, e.g.:
|
||||||
|
|
|
@ -8,10 +8,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"git.andreafazzi.eu/andrea/probo/cmd/filter"
|
"git.andreafazzi.eu/andrea/probo/cmd/filter"
|
||||||
|
"git.andreafazzi.eu/andrea/probo/cmd/util"
|
||||||
"bufio"
|
|
||||||
"io"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
@ -23,56 +20,22 @@ import (
|
||||||
var filterCmd = &cobra.Command{
|
var filterCmd = &cobra.Command{
|
||||||
Use: "filter",
|
Use: "filter",
|
||||||
Short: "Create a new filter",
|
Short: "Create a new filter",
|
||||||
Long: "Create a new filter to select quizzes and participants",
|
Long: "Create a new filter for selecting quizzes and participants",
|
||||||
Run: createFilter,
|
Run: createFilter,
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
createCmd.AddCommand(filterCmd)
|
createCmd.AddCommand(filterCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
|
||||||
|
|
||||||
// Cobra supports Persistent Flags which will work for this command
|
|
||||||
// and all subcommands, e.g.:
|
|
||||||
// filterCmd.PersistentFlags().String("foo", "", "A help for foo")
|
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
|
||||||
// is called directly, e.g.:
|
|
||||||
filterCmd.Flags().StringP("type", "t", "participants", "Select the type of filter (participants or quizzes)")
|
filterCmd.Flags().StringP("type", "t", "participants", "Select the type of filter (participants or quizzes)")
|
||||||
}
|
}
|
||||||
|
|
||||||
func createFilter(cmd *cobra.Command, args []string) {
|
func createFilter(cmd *cobra.Command, args []string) {
|
||||||
if len(os.Getenv("DEBUG")) > 0 {
|
f := util.LogToFile()
|
||||||
f, err := tea.LogToFile("debug.log", "debug")
|
if f != nil {
|
||||||
if err != nil {
|
|
||||||
fmt.Println("fatal:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
var b strings.Builder
|
|
||||||
|
|
||||||
stat, err := os.Stdin.Stat()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if stat.Mode()&os.ModeNamedPipe != 0 || stat.Size() != 0 {
|
|
||||||
reader := bufio.NewReader(os.Stdin)
|
|
||||||
for {
|
|
||||||
r, _, err := reader.ReadRune()
|
|
||||||
if err != nil && err == io.EOF {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
_, err = b.WriteRune(r)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error getting input:", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
path, err := cmd.Flags().GetString("input")
|
path, err := cmd.Flags().GetString("input")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -84,15 +47,15 @@ func createFilter(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lipgloss.SetColorProfile(termenv.TrueColor)
|
lipgloss.SetColorProfile(termenv.TrueColor)
|
||||||
|
|
||||||
model, err := tea.NewProgram(
|
model, err := tea.NewProgram(
|
||||||
filter.New(path, filterType, strings.TrimSpace(b.String())),
|
filter.New(path, filterType, util.ReadStdin()),
|
||||||
tea.WithOutput(os.Stderr),
|
tea.WithOutput(os.Stderr),
|
||||||
).Run()
|
).Run()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error running program:", err)
|
fmt.Println("Error running program:", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := model.(*filter.FilterModel)
|
result := model.(*filter.FilterModel)
|
||||||
if result.Result != "" {
|
if result.Result != "" {
|
||||||
fmt.Fprintf(os.Stdout, result.Result)
|
fmt.Fprintf(os.Stdout, result.Result)
|
||||||
|
|
|
@ -232,23 +232,24 @@ func (m *FilterModel) marshalJSON() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if m.InputJson != "" {
|
if m.InputJson != "" {
|
||||||
result := make([]interface{}, 2)
|
// result := make([]interface{}, 2)
|
||||||
err := json.Unmarshal([]byte(m.InputJson), &result[0])
|
// err := json.Unmarshal([]byte(m.InputJson), &result[0])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
filtered := fmt.Sprintf("{\"%s\": %s}", m.filterType, m.FilteredJson)
|
// filtered := fmt.Sprintf("{\"%s\": %s}", m.filterType, m.FilteredJson)
|
||||||
err = json.Unmarshal([]byte(filtered), &result[1])
|
// err = json.Unmarshal([]byte(filtered), &result[1])
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
resultJson, err := json.Marshal(result)
|
// resultJson, err := json.Marshal(result)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
panic(err)
|
// panic(err)
|
||||||
}
|
// }
|
||||||
m.Result = string(resultJson)
|
// m.Result = string(resultJson)
|
||||||
|
m.Result = fmt.Sprintf("{%s, \"%s\": %s}", strings.Trim(m.InputJson, "{}"), m.filterType, m.FilteredJson)
|
||||||
} else {
|
} else {
|
||||||
var result interface{}
|
var result interface{}
|
||||||
|
|
||||||
|
|
|
@ -1,40 +1,59 @@
|
||||||
/*
|
/*
|
||||||
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.andreafazzi.eu/andrea/probo/cmd/session"
|
||||||
|
"git.andreafazzi.eu/andrea/probo/cmd/util"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/muesli/termenv"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// sessionCmd represents the session command
|
// sessionCmd represents the session command
|
||||||
var sessionCmd = &cobra.Command{
|
var sessionCmd = &cobra.Command{
|
||||||
Use: "session",
|
Use: "session",
|
||||||
Short: "A brief description of your command",
|
Short: "Create a new session or update a given one",
|
||||||
Long: `A longer description that spans multiple lines and likely contains examples
|
Long: "Create a new session or update a given one.",
|
||||||
and usage of using your command. For example:
|
Run: updateSession,
|
||||||
|
|
||||||
Cobra is a CLI library for Go that empowers applications.
|
|
||||||
This application is a tool to generate the needed files
|
|
||||||
to quickly create a Cobra application.`,
|
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
|
||||||
fmt.Println("session called")
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
createCmd.AddCommand(sessionCmd)
|
updateCmd.AddCommand(sessionCmd)
|
||||||
|
|
||||||
|
sessionCmd.Flags().StringP("script", "s", "", "Execute a tengo script to initiate a session")
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateSession(cmd *cobra.Command, args []string) {
|
||||||
|
f := util.LogToFile()
|
||||||
|
if f != nil {
|
||||||
|
defer f.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
path, err := cmd.Flags().GetString("script")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
lipgloss.SetColorProfile(termenv.TrueColor)
|
||||||
|
|
||||||
|
model, err := tea.NewProgram(
|
||||||
|
session.New(path, util.ReadStdin()),
|
||||||
|
tea.WithOutput(os.Stderr),
|
||||||
|
).Run()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error running program:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
result := model.(*session.SessionModel)
|
||||||
|
if result.Result != "" {
|
||||||
|
fmt.Fprintf(os.Stdout, result.Result)
|
||||||
|
}
|
||||||
|
fmt.Println("session called", path, model)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
|
||||||
|
|
||||||
// Cobra supports Persistent Flags which will work for this command
|
|
||||||
// and all subcommands, e.g.:
|
|
||||||
// sessionCmd.PersistentFlags().String("foo", "", "A help for foo")
|
|
||||||
|
|
||||||
// Cobra supports local flags which will only run when this command
|
|
||||||
// is called directly, e.g.:
|
|
||||||
// sessionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
|
||||||
}
|
}
|
||||||
|
|
9
cmd/session/format.go
Normal file
9
cmd/session/format.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
var (
|
||||||
|
stateFormats = map[int][]string{
|
||||||
|
BrowseState: []string{"BROWSE 📖", "Use the navigation keys to browse the content. Press enter to return the result.", "STORE 🟢"},
|
||||||
|
LoadingStoreState: []string{"LOAD %s", "Loading the store...", "STORE 🔴"},
|
||||||
|
ErrorState: []string{"ERROR 📖", "%v", "STORE 🟢"},
|
||||||
|
}
|
||||||
|
)
|
19
cmd/session/message.go
Normal file
19
cmd/session/message.go
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import "git.andreafazzi.eu/andrea/probo/pkg/store/file"
|
||||||
|
|
||||||
|
type storeLoadedMsg struct {
|
||||||
|
store *file.SessionFileStore
|
||||||
|
}
|
||||||
|
|
||||||
|
type resultMsg struct {
|
||||||
|
result []any
|
||||||
|
}
|
||||||
|
|
||||||
|
type errorMsg struct {
|
||||||
|
error error
|
||||||
|
}
|
||||||
|
|
||||||
|
type scriptExecutedMsg struct {
|
||||||
|
result string
|
||||||
|
}
|
471
cmd/session/session.go
Normal file
471
cmd/session/session.go
Normal file
|
@ -0,0 +1,471 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"git.andreafazzi.eu/andrea/probo/pkg/models"
|
||||||
|
"git.andreafazzi.eu/andrea/probo/pkg/store/file"
|
||||||
|
"github.com/alecthomas/chroma/quick"
|
||||||
|
"github.com/charmbracelet/bubbles/help"
|
||||||
|
"github.com/charmbracelet/bubbles/key"
|
||||||
|
"github.com/charmbracelet/bubbles/spinner"
|
||||||
|
btTable "github.com/charmbracelet/bubbles/table"
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
"github.com/charmbracelet/glamour"
|
||||||
|
"github.com/charmbracelet/huh"
|
||||||
|
"github.com/charmbracelet/lipgloss"
|
||||||
|
"github.com/d5/tengo/v2"
|
||||||
|
"github.com/d5/tengo/v2/stdlib"
|
||||||
|
"github.com/remogatto/sugarfoam/components/form"
|
||||||
|
"github.com/remogatto/sugarfoam/components/group"
|
||||||
|
"github.com/remogatto/sugarfoam/components/header"
|
||||||
|
"github.com/remogatto/sugarfoam/components/statusbar"
|
||||||
|
"github.com/remogatto/sugarfoam/components/table"
|
||||||
|
"github.com/remogatto/sugarfoam/components/viewport"
|
||||||
|
"github.com/remogatto/sugarfoam/layout"
|
||||||
|
"github.com/remogatto/sugarfoam/layout/tiled"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SessionModel struct {
|
||||||
|
// UI
|
||||||
|
form *form.Model
|
||||||
|
viewport *viewport.Model
|
||||||
|
table *table.Model
|
||||||
|
group *group.Model
|
||||||
|
help help.Model
|
||||||
|
statusBar *statusbar.Model
|
||||||
|
spinner spinner.Model
|
||||||
|
|
||||||
|
// Layout
|
||||||
|
document *layout.Layout
|
||||||
|
|
||||||
|
// Key bindings
|
||||||
|
bindings *keyBindings
|
||||||
|
|
||||||
|
// file store
|
||||||
|
store *file.SessionFileStore
|
||||||
|
result []any
|
||||||
|
|
||||||
|
// json
|
||||||
|
FilteredJson string
|
||||||
|
InputJson string
|
||||||
|
Result string
|
||||||
|
|
||||||
|
// session
|
||||||
|
session *models.Session
|
||||||
|
|
||||||
|
// markdown
|
||||||
|
mdRenderer *glamour.TermRenderer
|
||||||
|
|
||||||
|
// filter file
|
||||||
|
scriptFilePath string
|
||||||
|
|
||||||
|
state int
|
||||||
|
}
|
||||||
|
|
||||||
|
type keyBindings struct {
|
||||||
|
group *group.Model
|
||||||
|
|
||||||
|
quit, enter key.Binding
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k *keyBindings) ShortHelp() []key.Binding {
|
||||||
|
keys := make([]key.Binding, 0)
|
||||||
|
|
||||||
|
current := k.group.Current()
|
||||||
|
|
||||||
|
switch item := current.(type) {
|
||||||
|
case *viewport.Model:
|
||||||
|
keys = append(
|
||||||
|
keys,
|
||||||
|
item.KeyMap.Up,
|
||||||
|
item.KeyMap.Down,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
keys = append(
|
||||||
|
keys,
|
||||||
|
k.quit,
|
||||||
|
)
|
||||||
|
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (k keyBindings) FullHelp() [][]key.Binding {
|
||||||
|
return [][]key.Binding{
|
||||||
|
{
|
||||||
|
k.quit,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newBindings(g *group.Model) *keyBindings {
|
||||||
|
return &keyBindings{
|
||||||
|
group: g,
|
||||||
|
quit: key.NewBinding(
|
||||||
|
key.WithKeys("esc"), key.WithHelp("esc", "Quit app"),
|
||||||
|
),
|
||||||
|
enter: key.NewBinding(
|
||||||
|
key.WithKeys("enter"), key.WithHelp("enter", "Quit app and return the results"),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(path string, stdin string) *SessionModel {
|
||||||
|
form := form.New(
|
||||||
|
form.WithGroups(huh.NewGroup(
|
||||||
|
huh.NewInput().
|
||||||
|
Title("Session name").
|
||||||
|
Description("Enter the name of the session"),
|
||||||
|
)))
|
||||||
|
|
||||||
|
form.
|
||||||
|
WithShowHelp(false).
|
||||||
|
WithTheme(huh.ThemeDracula())
|
||||||
|
|
||||||
|
viewport := viewport.New()
|
||||||
|
|
||||||
|
table := table.New(table.WithRelWidths(20, 30, 30, 20))
|
||||||
|
table.Model.SetColumns([]btTable.Column{
|
||||||
|
{Title: "Token", Width: 20},
|
||||||
|
{Title: "Lastname", Width: 20},
|
||||||
|
{Title: "Firstname", Width: 20},
|
||||||
|
{Title: "Class", Width: 20},
|
||||||
|
})
|
||||||
|
|
||||||
|
help := help.New()
|
||||||
|
|
||||||
|
group := group.New(
|
||||||
|
group.WithItems(form, table, viewport),
|
||||||
|
group.WithLayout(
|
||||||
|
layout.New(
|
||||||
|
layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Padding(1, 0, 1, 0)}),
|
||||||
|
layout.WithItem(form),
|
||||||
|
layout.WithItem(tiled.New(table, viewport)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
bindings := newBindings(group)
|
||||||
|
statusBar := statusbar.New(bindings)
|
||||||
|
|
||||||
|
s := spinner.New(
|
||||||
|
spinner.WithStyle(
|
||||||
|
lipgloss.NewStyle().Foreground(lipgloss.Color("265"))),
|
||||||
|
)
|
||||||
|
s.Spinner = spinner.Dot
|
||||||
|
|
||||||
|
header := header.New(
|
||||||
|
header.WithContent(
|
||||||
|
lipgloss.NewStyle().
|
||||||
|
Bold(true).
|
||||||
|
Border(lipgloss.NormalBorder(), false, false, true, false).
|
||||||
|
Render("✨ Create session ✨"),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
document := layout.New(
|
||||||
|
layout.WithStyles(&layout.Styles{Container: lipgloss.NewStyle().Margin(1)}),
|
||||||
|
layout.WithItem(header),
|
||||||
|
layout.WithItem(group),
|
||||||
|
layout.WithItem(statusBar),
|
||||||
|
)
|
||||||
|
|
||||||
|
renderer, err := glamour.NewTermRenderer(
|
||||||
|
glamour.WithStandardStyle("dracula"),
|
||||||
|
glamour.WithWordWrap(80),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return &SessionModel{
|
||||||
|
form: form,
|
||||||
|
table: table,
|
||||||
|
viewport: viewport,
|
||||||
|
group: group,
|
||||||
|
statusBar: statusBar,
|
||||||
|
spinner: s,
|
||||||
|
document: document,
|
||||||
|
mdRenderer: renderer,
|
||||||
|
bindings: bindings,
|
||||||
|
help: help,
|
||||||
|
scriptFilePath: path,
|
||||||
|
InputJson: stdin,
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) Init() tea.Cmd {
|
||||||
|
var cmds []tea.Cmd
|
||||||
|
|
||||||
|
cmds = append(cmds, m.group.Init(), m.loadStore(), m.spinner.Tick)
|
||||||
|
|
||||||
|
m.group.Focus()
|
||||||
|
|
||||||
|
return tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
var cmds []tea.Cmd
|
||||||
|
|
||||||
|
switch msg := msg.(type) {
|
||||||
|
|
||||||
|
case tea.WindowSizeMsg:
|
||||||
|
m.handleWindowSize(msg)
|
||||||
|
|
||||||
|
case tea.KeyMsg:
|
||||||
|
switch {
|
||||||
|
case key.Matches(msg, m.bindings.quit):
|
||||||
|
m.FilteredJson = ""
|
||||||
|
return m, tea.Quit
|
||||||
|
|
||||||
|
case key.Matches(msg, m.bindings.enter):
|
||||||
|
m.marshalJSON()
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
|
||||||
|
case storeLoadedMsg:
|
||||||
|
cmds = append(cmds, m.handleStoreLoaded(msg))
|
||||||
|
|
||||||
|
case scriptExecutedMsg:
|
||||||
|
m.handleScriptExecuted(msg)
|
||||||
|
|
||||||
|
case errorMsg:
|
||||||
|
m.handleError(msg)
|
||||||
|
m.state = ErrorState
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds = m.handleState(msg, cmds)
|
||||||
|
|
||||||
|
return m, tea.Batch(cmds...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) View() string {
|
||||||
|
return m.document.View()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) executeScript(path string) tea.Cmd {
|
||||||
|
return func() tea.Msg {
|
||||||
|
if m.scriptFilePath == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionJson, err := json.Marshal(models.Session{Exams: map[string]*models.Exam{}})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
script, err := os.ReadFile(m.scriptFilePath)
|
||||||
|
if err != nil {
|
||||||
|
return errorMsg{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
s := tengo.NewScript(script)
|
||||||
|
|
||||||
|
s.SetImports(stdlib.GetModuleMap("fmt", "json"))
|
||||||
|
_ = s.Add("input", m.InputJson)
|
||||||
|
_ = s.Add("output", string(sessionJson))
|
||||||
|
|
||||||
|
// compile the source
|
||||||
|
c, err := s.Compile()
|
||||||
|
if err != nil {
|
||||||
|
return errorMsg{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := c.Run(); err != nil {
|
||||||
|
return errorMsg{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return scriptExecutedMsg{fmt.Sprintf("%s", c.Get("output"))}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) marshalJSON() {
|
||||||
|
var result interface{}
|
||||||
|
|
||||||
|
err := json.Unmarshal([]byte(m.FilteredJson), &result)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
resultJson, err := json.Marshal(result)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
m.Result = string(resultJson)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) showErrorOnStatusBar(err error) {
|
||||||
|
m.statusBar.SetContent(
|
||||||
|
stateFormats[ErrorState][0],
|
||||||
|
fmt.Sprintf(stateFormats[ErrorState][1], err),
|
||||||
|
stateFormats[ErrorState][2],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) updateTableContent(session *models.Session) {
|
||||||
|
rows := make([]btTable.Row, 0)
|
||||||
|
|
||||||
|
for token, exam := range session.Exams {
|
||||||
|
rows = append(rows, btTable.Row{
|
||||||
|
token,
|
||||||
|
exam.Participant.Lastname,
|
||||||
|
exam.Participant.Firstname,
|
||||||
|
exam.Participant.Attributes.Get("class"),
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
m.table.SetRows(rows)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) updateViewportContent(session *models.Session) {
|
||||||
|
currentToken := m.table.SelectedRow()[0]
|
||||||
|
currentExam := session.Exams[currentToken]
|
||||||
|
if currentExam == nil {
|
||||||
|
panic("Current token is not associate to any exam")
|
||||||
|
}
|
||||||
|
|
||||||
|
md, err := currentExam.ToMarkdown()
|
||||||
|
if err != nil {
|
||||||
|
m.showErrorOnStatusBar(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := m.mdRenderer.Render(md)
|
||||||
|
if err != nil {
|
||||||
|
m.showErrorOnStatusBar(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.viewport.SetContent(result)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) createMDRenderer(width int) *glamour.TermRenderer {
|
||||||
|
renderer, err := glamour.NewTermRenderer(
|
||||||
|
glamour.WithStandardStyle("dracula"),
|
||||||
|
glamour.WithWordWrap(m.viewport.GetWidth()),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return renderer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) handleWindowSize(msg tea.WindowSizeMsg) {
|
||||||
|
m.group.SetSize(msg.Width, msg.Height)
|
||||||
|
m.document.SetSize(msg.Width, msg.Height)
|
||||||
|
m.mdRenderer = m.createMDRenderer(msg.Width)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) handleError(msg tea.Msg) {
|
||||||
|
err := msg.(errorMsg)
|
||||||
|
|
||||||
|
m.statusBar.SetContent(
|
||||||
|
stateFormats[ErrorState][0],
|
||||||
|
fmt.Sprintf(stateFormats[ErrorState][1], err.error),
|
||||||
|
stateFormats[ErrorState][2],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) handleScriptExecuted(msg tea.Msg) {
|
||||||
|
session := new(models.Session)
|
||||||
|
jsonData := []byte(msg.(scriptExecutedMsg).result)
|
||||||
|
|
||||||
|
err := json.Unmarshal(jsonData, &session)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.session = session
|
||||||
|
|
||||||
|
m.updateTableContent(session)
|
||||||
|
m.updateViewportContent(session)
|
||||||
|
|
||||||
|
m.state = BrowseState
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) handleStoreLoaded(msg tea.Msg) tea.Cmd {
|
||||||
|
storeMsg := msg.(storeLoadedMsg)
|
||||||
|
m.store = storeMsg.store
|
||||||
|
|
||||||
|
return m.executeScript(m.scriptFilePath)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) handleState(msg tea.Msg, cmds []tea.Cmd) []tea.Cmd {
|
||||||
|
_, cmd := m.group.Update(msg)
|
||||||
|
|
||||||
|
if m.state == LoadingStoreState {
|
||||||
|
return m.updateSpinner(msg, cmd, cmds)
|
||||||
|
}
|
||||||
|
|
||||||
|
if m.state == BrowseState {
|
||||||
|
m.updateViewportContent(m.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmds = append(cmds, cmd /*, m.query(m.textInput.Value())*/)
|
||||||
|
|
||||||
|
if m.state != ErrorState {
|
||||||
|
m.statusBar.SetContent(stateFormats[BrowseState]...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cmds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) updateSpinner(msg tea.Msg, cmd tea.Cmd, cmds []tea.Cmd) []tea.Cmd {
|
||||||
|
m.spinner, cmd = m.spinner.Update(msg)
|
||||||
|
|
||||||
|
m.statusBar.SetContent(fmt.Sprintf(stateFormats[m.state][0], m.spinner.View()), stateFormats[m.state][1], stateFormats[m.state][2])
|
||||||
|
|
||||||
|
cmds = append(cmds, cmd)
|
||||||
|
|
||||||
|
return cmds
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SessionModel) loadStore() tea.Cmd {
|
||||||
|
return func() tea.Msg {
|
||||||
|
sStore, err := file.NewDefaultSessionFileStore()
|
||||||
|
if err != nil {
|
||||||
|
return errorMsg{err}
|
||||||
|
}
|
||||||
|
|
||||||
|
return storeLoadedMsg{sStore}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func toColoredJson(data []any) (string, error) {
|
||||||
|
result, err := json.MarshalIndent(data, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
coloredBytes := make([]byte, 0)
|
||||||
|
buffer := bytes.NewBuffer(coloredBytes)
|
||||||
|
|
||||||
|
err = quick.Highlight(buffer, string(result), "json", "terminal16m", "dracula")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sanitize(buffer.String()), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func toJson(data []any) (string, error) {
|
||||||
|
result, err := json.Marshal(data)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return string(result), nil
|
||||||
|
}
|
||||||
|
func sanitize(text string) string {
|
||||||
|
// FIXME: The use of a standard '-' character causes rendering
|
||||||
|
// issues within the viewport. Further investigation is
|
||||||
|
// required to resolve this problem.
|
||||||
|
return strings.Replace(text, "-", "–", -1)
|
||||||
|
}
|
7
cmd/session/state.go
Normal file
7
cmd/session/state.go
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
const (
|
||||||
|
LoadingStoreState = iota
|
||||||
|
BrowseState
|
||||||
|
ErrorState
|
||||||
|
)
|
40
cmd/update.go
Normal file
40
cmd/update.go
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
|
*/
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
// updateCmd represents the update command
|
||||||
|
var updateCmd = &cobra.Command{
|
||||||
|
Use: "update",
|
||||||
|
Short: "A brief description of your command",
|
||||||
|
Long: `A longer description that spans multiple lines and likely contains examples
|
||||||
|
and usage of using your command. For example:
|
||||||
|
|
||||||
|
Cobra is a CLI library for Go that empowers applications.
|
||||||
|
This application is a tool to generate the needed files
|
||||||
|
to quickly create a Cobra application.`,
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
fmt.Println("update called")
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
rootCmd.AddCommand(updateCmd)
|
||||||
|
|
||||||
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
// Cobra supports Persistent Flags which will work for this command
|
||||||
|
// and all subcommands, e.g.:
|
||||||
|
// updateCmd.PersistentFlags().String("foo", "", "A help for foo")
|
||||||
|
|
||||||
|
// Cobra supports local flags which will only run when this command
|
||||||
|
// is called directly, e.g.:
|
||||||
|
// updateCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
|
}
|
49
cmd/util/util.go
Normal file
49
cmd/util/util.go
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
|
)
|
||||||
|
|
||||||
|
func LogToFile() *os.File {
|
||||||
|
if len(os.Getenv("DEBUG")) > 0 {
|
||||||
|
f, err := tea.LogToFile("probo-debug.log", "[DEBUG]")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("fatal:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadStdin() string {
|
||||||
|
var b strings.Builder
|
||||||
|
|
||||||
|
stat, err := os.Stdin.Stat()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if stat.Mode()&os.ModeNamedPipe != 0 || stat.Size() != 0 {
|
||||||
|
reader := bufio.NewReader(os.Stdin)
|
||||||
|
for {
|
||||||
|
r, _, err := reader.ReadRune()
|
||||||
|
if err != nil && err == io.EOF {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
_, err = b.WriteRune(r)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error getting input:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimSpace(b.String())
|
||||||
|
}
|
17
go.mod
17
go.mod
|
@ -3,38 +3,38 @@ module git.andreafazzi.eu/andrea/probo
|
||||||
go 1.21.6
|
go 1.21.6
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2
|
github.com/alecthomas/chroma v0.10.0
|
||||||
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181
|
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181
|
||||||
github.com/charmbracelet/bubbletea v0.25.0
|
github.com/charmbracelet/bubbletea v0.25.0
|
||||||
|
github.com/charmbracelet/huh v0.3.0
|
||||||
github.com/charmbracelet/lipgloss v0.10.0
|
github.com/charmbracelet/lipgloss v0.10.0
|
||||||
|
github.com/d5/tengo/v2 v2.17.0
|
||||||
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
|
github.com/gocarina/gocsv v0.0.0-20231116093920-b87c2d0e983a
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
github.com/itchyny/gojq v0.12.14
|
github.com/itchyny/gojq v0.12.14
|
||||||
|
github.com/lmittmann/tint v1.0.4
|
||||||
|
github.com/muesli/termenv v0.15.2
|
||||||
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8
|
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8
|
||||||
github.com/remogatto/sugarfoam v0.0.0-20240324175639-28e6bae1b225
|
github.com/remogatto/sugarfoam v0.0.0-20240418083243-766dd70853af
|
||||||
github.com/spf13/cobra v1.8.0
|
github.com/spf13/cobra v1.8.0
|
||||||
github.com/spf13/viper v1.18.2
|
github.com/spf13/viper v1.18.2
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
gorm.io/gorm v1.25.6
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/atotto/clipboard v0.1.4 // indirect
|
github.com/atotto/clipboard v0.1.4 // indirect
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||||
|
github.com/catppuccin/go v0.2.0 // indirect
|
||||||
github.com/containerd/console v1.0.4 // indirect
|
github.com/containerd/console v1.0.4 // indirect
|
||||||
github.com/fatih/color v1.14.1 // indirect
|
github.com/dlclark/regexp2 v1.4.0 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
|
||||||
github.com/kr/pretty v0.3.1 // indirect
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||||
github.com/magiconair/properties v1.8.7 // indirect
|
github.com/magiconair/properties v1.8.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-localereader v0.0.1 // indirect
|
github.com/mattn/go-localereader v0.0.1 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
|
@ -42,7 +42,6 @@ require (
|
||||||
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
|
||||||
github.com/muesli/cancelreader v0.2.2 // indirect
|
github.com/muesli/cancelreader v0.2.2 // indirect
|
||||||
github.com/muesli/reflow v0.3.0 // indirect
|
github.com/muesli/reflow v0.3.0 // indirect
|
||||||
github.com/muesli/termenv v0.15.2 // indirect
|
|
||||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||||
github.com/rivo/uniseg v0.4.7 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
github.com/rogpeppe/go-internal v1.9.0 // indirect
|
||||||
|
|
37
go.sum
37
go.sum
|
@ -1,25 +1,35 @@
|
||||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2 h1:ZBbLwSJqkHBuFDA6DUhhse0IGJ7T5bemHyNILUjvOq4=
|
github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
|
||||||
github.com/TylerBrock/colorjson v0.0.0-20200706003622-8a50f05110d2/go.mod h1:VSw57q4QFiWDbRnjdX8Cb3Ow0SFncRw+bA/ofY6Q83w=
|
github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
|
||||||
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8=
|
||||||
|
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo=
|
||||||
|
github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek=
|
||||||
|
github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s=
|
||||||
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4=
|
||||||
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=
|
||||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8=
|
||||||
|
github.com/catppuccin/go v0.2.0 h1:ktBeIrIP42b/8FGiScP9sgrWOss3lw0Z5SktRoithGA=
|
||||||
|
github.com/catppuccin/go v0.2.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc=
|
||||||
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181 h1:ntdtXC9+kcgQYvqa6nyLZLniCEUOhWQknLlz38JpDpM=
|
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181 h1:ntdtXC9+kcgQYvqa6nyLZLniCEUOhWQknLlz38JpDpM=
|
||||||
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181/go.mod h1:Zlzkn8WOd6QS7RC1BXAY1iw1VLq+xT70UZ1vkEtnrvo=
|
github.com/charmbracelet/bubbles v0.18.1-0.20240309002305-b9e62cbfe181/go.mod h1:Zlzkn8WOd6QS7RC1BXAY1iw1VLq+xT70UZ1vkEtnrvo=
|
||||||
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
|
github.com/charmbracelet/bubbletea v0.25.0 h1:bAfwk7jRz7FKFl9RzlIULPkStffg5k6pNt5dywy4TcM=
|
||||||
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
|
github.com/charmbracelet/bubbletea v0.25.0/go.mod h1:EN3QDR1T5ZdWmdfDzYcqOCAps45+QIJbLOBxmVNWNNg=
|
||||||
|
github.com/charmbracelet/huh v0.3.0 h1:CxPplWkgW2yUTDDG0Z4S5HH8SJOosWHd4LxCvi0XsKE=
|
||||||
|
github.com/charmbracelet/huh v0.3.0/go.mod h1:fujUdKX8tC45CCSaRQdw789O6uaCRwx8l2NDyKfC4jA=
|
||||||
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
github.com/charmbracelet/lipgloss v0.10.0 h1:KWeXFSexGcfahHX+54URiZGkBFazf70JNMtwg/AFW3s=
|
||||||
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
github.com/charmbracelet/lipgloss v0.10.0/go.mod h1:Wig9DSfvANsxqkRsqj6x87irdy123SR4dOXlKa91ciE=
|
||||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
|
github.com/d5/tengo/v2 v2.17.0 h1:BWUN9NoJzw48jZKiYDXDIF3QrIVZRm1uV1gTzeZ2lqM=
|
||||||
|
github.com/d5/tengo/v2 v2.17.0/go.mod h1:XRGjEs5I9jYIKTxly6HCF8oiiilk5E/RYXOZ5b0DZC8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/fatih/color v1.14.1 h1:qfhVLaG5s+nCROl1zJsZRxFeYrHLqWroPOQ8BWiNb4w=
|
github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E=
|
||||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
|
@ -32,29 +42,22 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8=
|
|
||||||
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/itchyny/gojq v0.12.14 h1:6k8vVtsrhQSYgSGg827AD+PVVaB1NLXEdX+dda2oZCc=
|
github.com/itchyny/gojq v0.12.14 h1:6k8vVtsrhQSYgSGg827AD+PVVaB1NLXEdX+dda2oZCc=
|
||||||
github.com/itchyny/gojq v0.12.14/go.mod h1:y1G7oO7XkcR1LPZO59KyoCRy08T3j9vDYRV0GgYSS+s=
|
github.com/itchyny/gojq v0.12.14/go.mod h1:y1G7oO7XkcR1LPZO59KyoCRy08T3j9vDYRV0GgYSS+s=
|
||||||
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE=
|
||||||
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
|
||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/lmittmann/tint v1.0.4 h1:LeYihpJ9hyGvE0w+K2okPTGUdVLfng1+nDNVR4vWISc=
|
||||||
|
github.com/lmittmann/tint v1.0.4/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE=
|
||||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
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/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
|
||||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4=
|
||||||
|
@ -80,8 +83,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8 h1:nRDwTcxV9B3elxMt+1xINX0bwaPdpouqp5fbynexY8U=
|
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8 h1:nRDwTcxV9B3elxMt+1xINX0bwaPdpouqp5fbynexY8U=
|
||||||
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8/go.mod h1:jOEnp79oIHy5cvQSHeLcgVJk1GHOOHJHQWps/d1N5Yo=
|
github.com/remogatto/prettytest v0.0.0-20200211072524-6d385e11dcb8/go.mod h1:jOEnp79oIHy5cvQSHeLcgVJk1GHOOHJHQWps/d1N5Yo=
|
||||||
github.com/remogatto/sugarfoam v0.0.0-20240324175639-28e6bae1b225 h1:LYFmm/8fYZQNhGBC8bHHZbRkfLeA0W1d25nfuPnRG8U=
|
github.com/remogatto/sugarfoam v0.0.0-20240418083243-766dd70853af h1:rSEwVRdJxMq4RK2kI1LEVhM5J3yg3pcvlRYy1vjn7mQ=
|
||||||
github.com/remogatto/sugarfoam v0.0.0-20240324175639-28e6bae1b225/go.mod h1:MkNrg58aCSx3bijbdHD+E02TmJ6TfGgOim78puJjBOU=
|
github.com/remogatto/sugarfoam v0.0.0-20240418083243-766dd70853af/go.mod h1:WeyW6WPrlPDwa48kDIytaLxXKyRjOwLp4BEd2tEGY1Y=
|
||||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
|
@ -109,6 +112,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||||
|
@ -123,7 +127,6 @@ golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 h1:hNQpMuAJe5CtcUqCXaWga3FHu
|
||||||
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
|
||||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||||
|
@ -142,5 +145,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/gorm v1.25.6 h1:V92+vVda1wEISSOMtodHVRcUIOPYa2tgQtyF+DfFx+A=
|
|
||||||
gorm.io/gorm v1.25.6/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
|
||||||
|
|
|
@ -12,6 +12,8 @@ github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZs
|
||||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
github.com/disintegration/gift v1.2.1/go.mod h1:Jh2i7f7Q2BM7Ezno3PhfezbR1xpUg9dUg3/RlKGr4HI=
|
||||||
|
github.com/disintegration/imageorient v0.0.0-20180920195336-8147d86e83ec/go.mod h1:K0KBFIr1gWu/C1Gp10nFAcAE4hsB7JxE6OgLijrJ8Sk=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
github.com/fatih/color v1.14.1/go.mod h1:2oHN61fhTpgcxD3TSWCgKDiH1+x4OiDVVGH8WlgGZGg=
|
||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
|
@ -41,11 +43,14 @@ github.com/nats-io/nkeys v0.4.6/go.mod h1:4DxZNzenSVd1cYQoAa8948QY3QDjrHfcfVADym
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
github.com/pkg/sftp v1.13.6/go.mod h1:tz1ryNURKu77RL+GuCzmoJYxQczL3wLNNpPWagdg4Qk=
|
||||||
|
github.com/remogatto/imgcat v0.0.0-20240318115229-ee6a34ad38fe/go.mod h1:e6G+BhMs87z7k9UKiGmV8tLWguKaNic9zlb3N+yC5Vc=
|
||||||
github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg=
|
github.com/sagikazarmark/crypt v0.17.0/go.mod h1:SMtHTvdmsZMuY/bpZoqokSoChIrcJ/epOxZN58PbZDg=
|
||||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y=
|
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f h1:MvTmaQdww/z0Q4wrYjDSCcZ78NoftLQyHBSLW/Cx79Y=
|
||||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA=
|
||||||
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y=
|
||||||
|
github.com/srwiley/oksvg v0.0.0-20220128195007-1f435e4c2b44/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q=
|
||||||
|
github.com/srwiley/rasterx v0.0.0-20220128185129-2efea2b9ea41/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
|
go.etcd.io/etcd/api/v3 v3.5.10/go.mod h1:TidfmT4Uycad3NM/o25fG3J07odo4GBB9hoxaodFCtI=
|
||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
|
go.etcd.io/etcd/client/pkg/v3 v3.5.10/go.mod h1:DYivfIviIuQ8+/lCq4vcxuseg2P2XbHygkKwFo9fc8U=
|
||||||
|
@ -54,12 +59,12 @@ go.etcd.io/etcd/client/v3 v3.5.10/go.mod h1:RVeBnDz2PUEZqTpgqwAtUd8nAPf5kjyFyND7
|
||||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
|
golang.org/x/image v0.0.0-20220413100746-70e8d0d3baa9/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
|
||||||
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
|
||||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
|
|
@ -10,9 +10,8 @@ import (
|
||||||
type Exam struct {
|
type Exam struct {
|
||||||
Meta
|
Meta
|
||||||
|
|
||||||
SessionID string
|
Participant *Participant `json:"participant"`
|
||||||
Participant *Participant
|
Quizzes []*Quiz `json:"quizzes"`
|
||||||
Quizzes []*Quiz
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exam) String() string {
|
func (e *Exam) String() string {
|
||||||
|
@ -35,3 +34,17 @@ func (e *Exam) Marshal() ([]byte, error) {
|
||||||
func (e *Exam) Unmarshal(data []byte) error {
|
func (e *Exam) Unmarshal(data []byte) error {
|
||||||
return json.Unmarshal(data, e)
|
return json.Unmarshal(data, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Exam) ToMarkdown() (string, error) {
|
||||||
|
result := ""
|
||||||
|
for _, quiz := range e.Quizzes {
|
||||||
|
quizMD, err := QuizToMarkdown(quiz)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
result += fmt.Sprintf(quizMD)
|
||||||
|
result += "\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
return strings.TrimRight(fmt.Sprintf("# %s %s \n %s", e.Participant.Lastname, e.Participant.Firstname, result), "\n"), nil
|
||||||
|
}
|
||||||
|
|
|
@ -9,16 +9,16 @@ import (
|
||||||
type Session struct {
|
type Session struct {
|
||||||
Meta
|
Meta
|
||||||
|
|
||||||
Name string
|
Title string `json:"name"`
|
||||||
Exams map[string]*Exam
|
Exams map[string]*Exam `json:"exams"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) String() string {
|
func (s *Session) String() string {
|
||||||
return s.Name
|
return s.Title
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) GetHash() string {
|
func (s *Session) GetHash() string {
|
||||||
return fmt.Sprintf("%x", sha256.Sum256([]byte(s.Name)))
|
return fmt.Sprintf("%x", sha256.Sum256([]byte(s.Title)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) Marshal() ([]byte, error) {
|
func (s *Session) Marshal() ([]byte, error) {
|
||||||
|
|
Loading…
Reference in a new issue