package cli import ( "bufio" "errors" "fmt" "log" "os" "regexp" "strconv" "strings" "gitea.elara.ws/Hazel/music-kraken/internal/common" "gitea.elara.ws/Hazel/music-kraken/internal/common/color" "gitea.elara.ws/Hazel/music-kraken/internal/data" "gitea.elara.ws/Hazel/music-kraken/internal/plugin" ) func printResults(musicObjects []data.MusicObject) { if len(musicObjects) <= 0 { return } results := make([]string, len(musicObjects)) for i, m := range musicObjects { results[i] = common.ZeroPad(i, 2) + ": " if a, ok := m.(data.Artist); ok { results[i] += "#a " + a.Name } else if a, ok := m.(data.Album); ok { results[i] += "#r " + a.Name for _, artist := range a.Artists { results[i] += " - " + artist.Name } } else if a, ok := m.(data.Song); ok { results[i] += "#s " + a.Name if a.Album.Name != "" { results[i] += " - " + a.Album.Name } for _, artist := range a.Artists { results[i] += " - " + artist.Name } } sources := m.GetSources() if len(sources) > 0 { for _, source := range sources { results[i] += "\n\t- " + source.SourceType.Name + " " + string(source.ObjectType) + " " + source.Url } } else { results[i] = color.StrikeThrough + results[i] + color.Reset } } fmt.Println() fmt.Println(strings.Join(results, "\n")) fmt.Println() } type musicObjectStore [][]data.MusicObject func (s musicObjectStore) currentMusicObjects() ([]data.MusicObject, error) { if len(s) <= 0 { return []data.MusicObject{}, errors.New("no items to select from") } return (s)[len(s)-1], nil } var indexSelectionPattern = regexp.MustCompile(`^[\d ,]+$`) func interpretCommand(command string, store musicObjectStore) (musicObjectStore, error) { // going back in history if command == ".." { if len(store) <= 1 { return store, errors.New("can't go back") } return store[:len(store)-1], nil } // fetch special music object if indexSelectionPattern.MatchString(command) { currentMusicObjects, err := store.currentMusicObjects() if err != nil { return store, err } var fetched data.MusicObject for _, stringIndex := range strings.Split(command, ",") { index, _ := strconv.Atoi(strings.TrimSpace(stringIndex)) if index >= len(currentMusicObjects) || index < 0 { return store, errors.New(command + " is out of bounds [0 <= " + strconv.Itoa(index) + " <= " + strconv.Itoa(len(currentMusicObjects)-1) + "]") } current := currentMusicObjects[index] newFetched, err := plugin.Fetch(current) if err != nil { return store, err } if fetched == nil { fetched = newFetched } else { fetched = fetched.Merge(newFetched) } } return append(store, fetched.Related()), nil } // search in every other case currentMusicObjects, err := plugin.Search(command, plugin.SearchConfig{IgnoreErrors: false}) if err != nil { fmt.Println(err) fmt.Println() } return append(store, currentMusicObjects), nil } func Shell(commandsList ...[]string) { plugin.RegisterPlugin(&plugin.Musify{}) commands := []string{} if len(commandsList) > 0 { commands = commandsList[0] } fmt.Println("== MusicKraken Shell ==") fmt.Println() store := musicObjectStore{} var err error = nil for { var command string if len(commands) <= 0 { fmt.Print("> ") reader := bufio.NewReader(os.Stdin) command, err = reader.ReadString('\n') if err != nil { log.Fatal(err) } } else { command = commands[0] commands = commands[1:] } store, err = interpretCommand(strings.TrimSpace(command), store) if err != nil { fmt.Println() fmt.Println(color.Yellow + err.Error() + color.Reset) fmt.Println() } currentMusicObject, err := store.currentMusicObjects() if err == nil { printResults(currentMusicObject) } } }