diff --git a/anko.go b/anko.go deleted file mode 100644 index a242481..0000000 --- a/anko.go +++ /dev/null @@ -1,172 +0,0 @@ -package main - -import ( - "io/ioutil" - "os" - - "github.com/mattn/anko/core" - "github.com/mattn/anko/env" - "github.com/mattn/anko/vm" - _ "github.com/mattn/anko/packages" - "github.com/ztrue/tracerr" -) - - -type Anko struct { - env *env.Env -} - -func newAnko() Anko { - return Anko{ - core.Import(env.NewEnv()), - } -} - -// define defines new symbol and value to the Anko env -func (a *Anko) define(symbol string, value interface{}) error { - return a.env.DefineGlobal(symbol, value) -} - -// set sets new value to existing symbol. Use this when change value under an -// existing symbol. -func (a *Anko) set(symbol string, value interface{}) error { - return a.env.Set(symbol, value) -} - -// get gets value from anko env, returns error if symbol is not found. -func (a *Anko) get(symbol string) (interface{}, error) { - return a.env.Get(symbol) -} - -// getInt gets int value from symbol, returns golang default value if not found -func (a *Anko) getInt(symbol string) int { - v, err := a.env.Get(symbol) - if err != nil { - return 0 - } - - val, ok := v.(int64) - if !ok { - return 0 - } - - return int(val) -} - -// getString gets string value from symbol, returns golang default value if not -// found -func (a *Anko) getString(symbol string) string { - v, err := a.env.Get(symbol) - if err != nil { - return "" - } - - val, ok := v.(string) - if !ok { - return "" - } - - return val -} - -// getBool gets bool value from symbol, returns golang default value if not -// found -func (a *Anko) getBool(symbol string) bool { - v, err := a.env.Get(symbol) - if err != nil { - return false - } - - val, ok := v.(bool) - if !ok { - return false - } - - return val -} - -// execute executes anko script -func (a *Anko) execute(src string) (interface{}, error) { - return vm.Execute(a.env, nil, src) -} - -// executes user config with default config is executed first in order to apply -// default values -func execConfig(config string) error { - - const defaultConfig = ` - -// confirmation popup to add the whole playlist to the queue -confirm_bulk_add = true -confirm_on_exit = true -queue_loop = false -load_prev_queue = true -popup_timeout = "5s" -// change this to directory that contains mp3 files -music_dir = "~/music" -// url history of downloaded audio will be saved here -history_path = "~/.local/share/gomu/urls" -// some of the terminal supports unicode character -// you can set this to true to enable emojis -use_emoji = true -// initial volume when gomu starts up -volume = 80 -// if you experiencing error using this invidious instance, you can change it -// to another instance from this list: -// https://github.com/iv-org/documentation/blob/master/Invidious-Instances.md -invidious_instance = "https://vid.puffyan.us" - -// default emoji here is using awesome-terminal-fonts -// you can change these to your liking -emoji_playlist = "" -emoji_file = "" -emoji_loop = "ﯩ" -emoji_noloop = "" - -// not all colors can be reproducible in terminal -// changing hex colors may or may not produce expected result -color_accent = "#008B8B" -color_background = "none" -color_foreground = "#FFFFFF" -color_now_playing_title = "#017702" -color_playlist = "#008B8B" -color_popup = "#0A0F14" - -// vim: syntax=go -` - - // built-in functions - gomu.anko.define("debug_popup", debugPopup) - gomu.anko.define("input_popup", inputPopup) - gomu.anko.define("show_popup", defaultTimedPopup) - gomu.anko.define("shell", shell) - - cfg := expandTilde(config) - - _, err := os.Stat(cfg) - if os.IsNotExist(err) { - err = appendFile(cfg, defaultConfig) - if err != nil { - return tracerr.Wrap(err) - } - } - - content, err := ioutil.ReadFile(cfg) - if err != nil { - return tracerr.Wrap(err) - } - - // execute default config - _, err = gomu.anko.execute(defaultConfig) - if err != nil { - return tracerr.Wrap(err) - } - - // execute user config - _, err = gomu.anko.execute(string(content)) - if err != nil { - return tracerr.Wrap(err) - } - - return nil -} diff --git a/anko/anko.go b/anko/anko.go new file mode 100644 index 0000000..4932674 --- /dev/null +++ b/anko/anko.go @@ -0,0 +1,87 @@ +package anko + +import ( + "github.com/mattn/anko/core" + "github.com/mattn/anko/env" + "github.com/mattn/anko/vm" + _ "github.com/mattn/anko/packages" +) + + +type Anko struct { + env *env.Env +} + +func NewAnko() Anko { + return Anko{ + core.Import(env.NewEnv()), + } +} + +// define defines new symbol and value to the Anko env +func (a *Anko) Define(symbol string, value interface{}) error { + return a.env.DefineGlobal(symbol, value) +} + +// set sets new value to existing symbol. Use this when change value under an +// existing symbol. +func (a *Anko) Set(symbol string, value interface{}) error { + return a.env.Set(symbol, value) +} + +// get gets value from anko env, returns error if symbol is not found. +func (a *Anko) Get(symbol string) (interface{}, error) { + return a.env.Get(symbol) +} + +// getInt gets int value from symbol, returns golang default value if not found +func (a *Anko) GetInt(symbol string) int { + v, err := a.env.Get(symbol) + if err != nil { + return 0 + } + + val, ok := v.(int64) + if !ok { + return 0 + } + + return int(val) +} + +// getString gets string value from symbol, returns golang default value if not +// found +func (a *Anko) GetString(symbol string) string { + v, err := a.env.Get(symbol) + if err != nil { + return "" + } + + val, ok := v.(string) + if !ok { + return "" + } + + return val +} + +// getBool gets bool value from symbol, returns golang default value if not +// found +func (a *Anko) GetBool(symbol string) bool { + v, err := a.env.Get(symbol) + if err != nil { + return false + } + + val, ok := v.(bool) + if !ok { + return false + } + + return val +} + +// execute executes anko script +func (a *Anko) Execute(src string) (interface{}, error) { + return vm.Execute(a.env, nil, src) +} diff --git a/colors.go b/colors.go index 7a0b485..f531e77 100644 --- a/colors.go +++ b/colors.go @@ -31,18 +31,18 @@ func newColor() *Colors { for k, v := range defaultColors { // color from the config file - cfgColor := anko.getString(k) + cfgColor := anko.GetString(k) if validHexColor(cfgColor) { continue } // use default value if invalid hex color was given - anko.set(k, v) + anko.Set(k, v) } // handle none background color var bgColor tcell.Color - bg := anko.getString("color_background") + bg := anko.GetString("color_background") if bg == "none" { bgColor = tcell.ColorDefault @@ -50,11 +50,11 @@ func newColor() *Colors { bgColor = tcell.GetColor(bg) } - accent := anko.getString("color_accent") - foreground := anko.getString("color_foreground") - popup := anko.getString("color_popup") - title := anko.getString("color_now_playing_title") - playlist := anko.getString("color_playlist") + accent := anko.GetString("color_accent") + foreground := anko.GetString("color_foreground") + popup := anko.GetString("color_popup") + title := anko.GetString("color_now_playing_title") + playlist := anko.GetString("color_playlist") color := &Colors{ accent: tcell.GetColor(accent), diff --git a/command.go b/command.go index 43d3560..ad33743 100644 --- a/command.go +++ b/command.go @@ -205,7 +205,7 @@ func (c Command) defineCommands() { c.define("bulk_add", func() { currNode := gomu.playlist.GetCurrentNode() - bulkAdd := anko.getBool("confirm_bulk_add") + bulkAdd := anko.GetBool("confirm_bulk_add") if !bulkAdd { gomu.playlist.addAllToQueue(currNode) @@ -321,7 +321,7 @@ func (c Command) defineCommands() { /* Global */ c.define("quit", func() { - confirmOnExit := anko.getBool("confirm_on_exit") + confirmOnExit := anko.GetBool("confirm_on_exit") if !confirmOnExit { err := gomu.quit(gomu.args) @@ -462,7 +462,7 @@ func (c Command) defineCommands() { }) for name, cmd := range c.commands { - err := gomu.anko.define(name, cmd) + err := gomu.anko.Define(name, cmd) if err != nil { logError(err) } diff --git a/gomu.go b/gomu.go index 381f177..6111987 100644 --- a/gomu.go +++ b/gomu.go @@ -3,6 +3,7 @@ package main import ( "github.com/rivo/tview" "github.com/ztrue/tracerr" + "github.com/issadarkthing/gomu/anko" ) var VERSION = "N/A" @@ -23,7 +24,7 @@ type Gomu struct { prevPanel Panel panels []Panel args Args - anko Anko + anko anko.Anko } // Creates new instance of gomu with default values @@ -31,7 +32,7 @@ func newGomu() *Gomu { gomu := &Gomu{ command: newCommand(), - anko: newAnko(), + anko: anko.NewAnko(), } return gomu diff --git a/player.go b/player.go index 3d6a8ac..66ad446 100644 --- a/player.go +++ b/player.go @@ -37,7 +37,7 @@ type Player struct { func newPlayer() *Player { - volume := gomu.anko.getInt("volume") + volume := gomu.anko.GetInt("volume") // Read initial volume from config initVol := absVolume(volume) diff --git a/playlist.go b/playlist.go index d00a4b9..97244f6 100644 --- a/playlist.go +++ b/playlist.go @@ -74,7 +74,7 @@ func newPlaylist(args Args) *Playlist { anko := gomu.anko - m := anko.getString("music_dir") + m := anko.GetString("music_dir") rootDir, err := filepath.Abs(expandTilde(m)) if err != nil { err = tracerr.Errorf("unable to find music directory: %e", err) @@ -89,11 +89,11 @@ func newPlaylist(args Args) *Playlist { var rootTextView string - useEmoji := anko.getBool("use_emoji") + useEmoji := anko.GetBool("use_emoji") if useEmoji { - emojiPlaylist := anko.getString("emoji_playlist") + emojiPlaylist := anko.GetString("emoji_playlist") rootTextView = fmt.Sprintf("%s %s", emojiPlaylist, path.Base(rootDir)) } else { @@ -572,7 +572,7 @@ func ytdl(url string, selPlaylist *tview.TreeNode) error { playlistPath := dir audioPath := extractFilePath(stdout.Bytes(), playlistPath) - historyPath := gomu.anko.getString("history_path") + historyPath := gomu.anko.GetString("history_path") err = appendFile(expandTilde(historyPath), url+"\n") if err != nil { @@ -729,12 +729,12 @@ func (p *Playlist) paste() error { } func setDisplayText(songName string) string { - useEmoji := gomu.anko.getBool("use_emoji") + useEmoji := gomu.anko.GetBool("use_emoji") if !useEmoji { return songName } - emojiFile := gomu.anko.getString("emoji_file") + emojiFile := gomu.anko.GetString("emoji_file") return fmt.Sprintf(" %s %s", emojiFile, songName) } diff --git a/popup.go b/popup.go index 11c1aac..5110245 100644 --- a/popup.go +++ b/popup.go @@ -68,7 +68,7 @@ func (s *Stack) pop() tview.Primitive { // Gets popup timeout from config file func getPopupTimeout() time.Duration { - dur := gomu.anko.getString("popup_timeout") + dur := gomu.anko.GetString("popup_timeout") m, err := time.ParseDuration(dur) if err != nil { diff --git a/queue.go b/queue.go index 412afe6..45da9d0 100644 --- a/queue.go +++ b/queue.go @@ -97,17 +97,17 @@ func (q *Queue) updateTitle() string { var loop string - isEmoji := gomu.anko.getBool("use_emoji") + isEmoji := gomu.anko.GetBool("use_emoji") if q.isLoop { if isEmoji { - loop = gomu.anko.getString("emoji_loop") + loop = gomu.anko.GetString("emoji_loop") } else { loop = "Loop" } } else { if isEmoji { - loop = gomu.anko.getString("emoji_noloop") + loop = gomu.anko.GetString("emoji_noloop") } else { loop = "No loop" } diff --git a/search.go b/search.go index bee5ea1..888a4f6 100644 --- a/search.go +++ b/search.go @@ -86,7 +86,7 @@ func getRequest(url string, v interface{}) error { func getSearchResult(query string) ([]YoutubeVideo, error) { query = url.QueryEscape(query) - domain := gomu.anko.getString("invidious_instance") + domain := gomu.anko.GetString("invidious_instance") targetUrl := domain + `/api/v1/search?q=` + query yt := []YoutubeVideo{} diff --git a/start.go b/start.go index 03cf2c5..9a76aaf 100644 --- a/start.go +++ b/start.go @@ -7,6 +7,7 @@ import ( "errors" "flag" "fmt" + "io/ioutil" "os" "os/signal" "strings" @@ -15,6 +16,7 @@ import ( "github.com/gdamore/tcell/v2" "github.com/rivo/tview" + "github.com/ztrue/tracerr" ) // Panel is used to keep track of childrens in slices @@ -27,6 +29,7 @@ type Panel interface { help() []string } +// Default values for command line arguments. const ( configPath = "~/.config/gomu/config" musicPath = "~/music" @@ -52,6 +55,88 @@ func getArgs() Args { return ar } + +// executes user config with default config is executed first in order to apply +// default values +func execConfig(config string) error { + + const defaultConfig = ` + +// confirmation popup to add the whole playlist to the queue +confirm_bulk_add = true +confirm_on_exit = true +queue_loop = false +load_prev_queue = true +popup_timeout = "5s" +// change this to directory that contains mp3 files +music_dir = "~/music" +// url history of downloaded audio will be saved here +history_path = "~/.local/share/gomu/urls" +// some of the terminal supports unicode character +// you can set this to true to enable emojis +use_emoji = true +// initial volume when gomu starts up +volume = 80 +// if you experiencing error using this invidious instance, you can change it +// to another instance from this list: +// https://github.com/iv-org/documentation/blob/master/Invidious-Instances.md +invidious_instance = "https://vid.puffyan.us" + +// default emoji here is using awesome-terminal-fonts +// you can change these to your liking +emoji_playlist = "" +emoji_file = "" +emoji_loop = "ﯩ" +emoji_noloop = "" + +// not all colors can be reproducible in terminal +// changing hex colors may or may not produce expected result +color_accent = "#008B8B" +color_background = "none" +color_foreground = "#FFFFFF" +color_now_playing_title = "#017702" +color_playlist = "#008B8B" +color_popup = "#0A0F14" + +// vim: syntax=go +` + + // built-in functions + gomu.anko.Define("debug_popup", debugPopup) + gomu.anko.Define("input_popup", inputPopup) + gomu.anko.Define("show_popup", defaultTimedPopup) + gomu.anko.Define("shell", shell) + + cfg := expandTilde(config) + + _, err := os.Stat(cfg) + if os.IsNotExist(err) { + err = appendFile(cfg, defaultConfig) + if err != nil { + return tracerr.Wrap(err) + } + } + + content, err := ioutil.ReadFile(cfg) + if err != nil { + return tracerr.Wrap(err) + } + + // execute default config + _, err = gomu.anko.Execute(defaultConfig) + if err != nil { + return tracerr.Wrap(err) + } + + // execute user config + _, err = gomu.anko.Execute(string(content)) + if err != nil { + return tracerr.Wrap(err) + } + + return nil +} + // Sets the layout of the application func layout(gomu *Gomu) *tview.Flex { flex := tview.NewFlex(). @@ -104,12 +189,12 @@ func start(application *tview.Application, args Args) { gomu.playingBar.setDefault() - isQueueLoop := gomu.anko.getBool("queue_loop") + isQueueLoop := gomu.anko.GetBool("queue_loop") gomu.player.isLoop = isQueueLoop gomu.queue.isLoop = gomu.player.isLoop - loadQueue := gomu.anko.getBool("load_prev_queue") + loadQueue := gomu.anko.GetBool("load_prev_queue") if !*args.empty && loadQueue { // load saved queue from previous session @@ -150,7 +235,7 @@ func start(application *tview.Application, args Args) { } // check for user defined keybindings - kb, err := gomu.anko.get("keybinds") + kb, err := gomu.anko.Get("keybinds") if err == nil { keybinds, ok := kb.(map[interface{}]interface{}) if !ok {