2020-08-11 01:50:40 +03:00
|
|
|
// Package config initializes all files required for Amfora, even those used by
|
|
|
|
// other packages. It also reads in the config file and initializes a Viper and
|
|
|
|
// the theme
|
2020-11-05 03:40:34 +03:00
|
|
|
//nolint:golint,goerr113
|
2020-06-18 23:54:48 +03:00
|
|
|
package config
|
|
|
|
|
|
|
|
import (
|
2020-07-10 02:28:39 +03:00
|
|
|
"fmt"
|
2020-06-18 23:54:48 +03:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
"runtime"
|
2020-06-22 18:56:55 +03:00
|
|
|
"strings"
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2021-04-07 19:56:32 +03:00
|
|
|
"code.rocketnine.space/tslocum/cview"
|
2021-02-17 22:17:13 +03:00
|
|
|
"github.com/gdamore/tcell/v2"
|
2020-06-18 23:54:48 +03:00
|
|
|
"github.com/makeworld-the-better-one/amfora/cache"
|
|
|
|
homedir "github.com/mitchellh/go-homedir"
|
2021-12-04 01:58:16 +03:00
|
|
|
"github.com/muesli/termenv"
|
2020-10-09 03:54:07 +03:00
|
|
|
"github.com/rkoesters/xdg/basedir"
|
|
|
|
"github.com/rkoesters/xdg/userdirs"
|
2020-06-18 23:54:48 +03:00
|
|
|
"github.com/spf13/viper"
|
|
|
|
)
|
|
|
|
|
|
|
|
var amforaAppData string // Where amfora files are stored on Windows - cached here
|
2020-06-22 00:35:19 +03:00
|
|
|
var configDir string
|
|
|
|
var configPath string
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2020-09-01 20:55:09 +03:00
|
|
|
var NewTabPath string
|
|
|
|
var CustomNewTab bool
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
var TofuStore = viper.New()
|
2020-06-22 00:35:19 +03:00
|
|
|
var tofuDBDir string
|
|
|
|
var tofuDBPath string
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2020-06-24 03:07:25 +03:00
|
|
|
// Bookmarks
|
2021-02-27 08:13:11 +03:00
|
|
|
var BkmkStore = viper.New() // TOML API for old bookmarks file
|
2020-06-24 03:07:25 +03:00
|
|
|
var bkmkDir string
|
2021-02-27 08:13:11 +03:00
|
|
|
var OldBkmkPath string // Old bookmarks file that used TOML format
|
|
|
|
var BkmkPath string // New XBEL (XML) bookmarks file, see #68
|
2020-06-24 03:07:25 +03:00
|
|
|
|
2020-07-10 02:28:39 +03:00
|
|
|
var DownloadsDir string
|
2020-12-14 22:28:07 +03:00
|
|
|
var TempDownloadsDir string
|
2020-07-10 02:28:39 +03:00
|
|
|
|
2020-11-28 01:01:29 +03:00
|
|
|
// Subscriptions
|
|
|
|
var subscriptionDir string
|
|
|
|
var SubscriptionPath string
|
2020-08-07 19:27:50 +03:00
|
|
|
|
2020-11-05 02:35:56 +03:00
|
|
|
// Command for opening HTTP(S) URLs in the browser, from "a-general.http" in config.
|
2020-11-05 02:47:27 +03:00
|
|
|
var HTTPCommand []string
|
2020-11-05 02:35:56 +03:00
|
|
|
|
2020-12-14 22:28:07 +03:00
|
|
|
type MediaHandler struct {
|
|
|
|
Cmd []string
|
|
|
|
NoPrompt bool
|
2020-12-25 07:38:12 +03:00
|
|
|
Stream bool
|
2020-12-14 22:28:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
var MediaHandlers = make(map[string]MediaHandler)
|
|
|
|
|
2021-02-17 22:17:13 +03:00
|
|
|
// Controlled by "a-general.scrollbar" in config
|
|
|
|
// Defaults to ScrollBarAuto on an invalid value
|
|
|
|
var ScrollBar cview.ScrollBarVisibility
|
|
|
|
|
2021-12-04 01:58:16 +03:00
|
|
|
// Whether the user's terminal is dark or light
|
|
|
|
// Defaults to dark, but is determined in Init()
|
|
|
|
// Used to prevent white text on a white background with the default theme
|
|
|
|
var hasDarkTerminalBackground bool
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
func Init() error {
|
2020-08-07 19:27:50 +03:00
|
|
|
|
|
|
|
// *** Set paths ***
|
2021-12-08 01:40:50 +03:00
|
|
|
// Windows uses paths under APPDATA, Unix systems use XDG paths
|
|
|
|
// Windows systems use XDG paths if variables are defined, see #255
|
2020-08-07 19:27:50 +03:00
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
home, err := homedir.Dir()
|
|
|
|
if err != nil {
|
2020-07-10 02:28:39 +03:00
|
|
|
return err
|
2020-06-18 23:54:48 +03:00
|
|
|
}
|
2020-06-24 03:07:25 +03:00
|
|
|
// Store AppData path
|
2020-08-27 18:47:57 +03:00
|
|
|
if runtime.GOOS == "windows" { //nolint:goconst
|
2020-06-18 23:54:48 +03:00
|
|
|
appdata, ok := os.LookupEnv("APPDATA")
|
|
|
|
if ok {
|
|
|
|
amforaAppData = filepath.Join(appdata, "amfora")
|
|
|
|
} else {
|
|
|
|
amforaAppData = filepath.Join(home, filepath.FromSlash("AppData/Roaming/amfora/"))
|
|
|
|
}
|
|
|
|
}
|
2020-06-24 03:07:25 +03:00
|
|
|
|
|
|
|
// Store config directory and file paths
|
2021-12-08 01:40:50 +03:00
|
|
|
if runtime.GOOS == "windows" && os.Getenv("XDG_CONFIG_HOME") == "" {
|
2020-06-22 00:35:19 +03:00
|
|
|
configDir = amforaAppData
|
|
|
|
} else {
|
2021-12-08 01:40:50 +03:00
|
|
|
// Unix / POSIX system, or Windows with XDG_CONFIG_HOME defined
|
2020-10-12 21:48:21 +03:00
|
|
|
configDir = filepath.Join(basedir.ConfigHome, "amfora")
|
2020-06-22 00:35:19 +03:00
|
|
|
}
|
|
|
|
configPath = filepath.Join(configDir, "config.toml")
|
|
|
|
|
2020-09-01 20:55:09 +03:00
|
|
|
// Search for a custom new tab
|
|
|
|
NewTabPath = filepath.Join(configDir, "newtab.gmi")
|
|
|
|
CustomNewTab = false
|
|
|
|
if _, err := os.Stat(NewTabPath); err == nil {
|
|
|
|
CustomNewTab = true
|
|
|
|
}
|
|
|
|
|
2020-06-24 03:07:25 +03:00
|
|
|
// Store TOFU db directory and file paths
|
2021-12-08 01:40:50 +03:00
|
|
|
if runtime.GOOS == "windows" && os.Getenv("XDG_CACHE_HOME") == "" {
|
2020-06-22 18:56:55 +03:00
|
|
|
// Windows just stores it in APPDATA along with other stuff
|
2020-06-22 00:35:19 +03:00
|
|
|
tofuDBDir = amforaAppData
|
|
|
|
} else {
|
|
|
|
// XDG cache dir on POSIX systems
|
2020-10-12 21:48:21 +03:00
|
|
|
tofuDBDir = filepath.Join(basedir.CacheHome, "amfora")
|
2020-06-22 00:35:19 +03:00
|
|
|
}
|
|
|
|
tofuDBPath = filepath.Join(tofuDBDir, "tofu.toml")
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2020-06-24 03:07:25 +03:00
|
|
|
// Store bookmarks dir and path
|
2021-12-08 01:40:50 +03:00
|
|
|
if runtime.GOOS == "windows" && os.Getenv("XDG_DATA_HOME") == "" {
|
2020-06-24 03:07:25 +03:00
|
|
|
// Windows just keeps it in APPDATA along with other Amfora files
|
|
|
|
bkmkDir = amforaAppData
|
|
|
|
} else {
|
|
|
|
// XDG data dir on POSIX systems
|
2020-10-12 21:48:21 +03:00
|
|
|
bkmkDir = filepath.Join(basedir.DataHome, "amfora")
|
2020-06-24 03:07:25 +03:00
|
|
|
}
|
2021-02-27 08:13:11 +03:00
|
|
|
OldBkmkPath = filepath.Join(bkmkDir, "bookmarks.toml")
|
|
|
|
BkmkPath = filepath.Join(bkmkDir, "bookmarks.xml")
|
2020-06-24 03:07:25 +03:00
|
|
|
|
2020-08-11 01:50:40 +03:00
|
|
|
// Feeds dir and path
|
2021-12-08 01:40:50 +03:00
|
|
|
if runtime.GOOS == "windows" && os.Getenv("XDG_DATA_HOME") == "" {
|
2020-08-11 01:50:40 +03:00
|
|
|
// In APPDATA beside other Amfora files
|
2020-11-28 01:01:29 +03:00
|
|
|
subscriptionDir = amforaAppData
|
2020-08-11 01:50:40 +03:00
|
|
|
} else {
|
|
|
|
// XDG data dir on POSIX systems
|
2021-12-08 01:40:50 +03:00
|
|
|
subscriptionDir = filepath.Join(basedir.DataHome, "amfora")
|
2020-08-11 01:50:40 +03:00
|
|
|
}
|
2020-11-28 01:01:29 +03:00
|
|
|
SubscriptionPath = filepath.Join(subscriptionDir, "subscriptions.json")
|
2020-08-11 01:50:40 +03:00
|
|
|
|
2020-08-07 19:27:50 +03:00
|
|
|
// *** Create necessary files and folders ***
|
2020-06-24 03:07:25 +03:00
|
|
|
|
|
|
|
// Config
|
2020-06-22 00:35:19 +03:00
|
|
|
err = os.MkdirAll(configDir, 0755)
|
2020-06-18 23:54:48 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-06-22 00:35:19 +03:00
|
|
|
f, err := os.OpenFile(configPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
|
2020-06-18 23:54:48 +03:00
|
|
|
if err == nil {
|
|
|
|
// Config file doesn't exist yet, write the default one
|
|
|
|
_, err = f.Write(defaultConf)
|
|
|
|
if err != nil {
|
|
|
|
f.Close()
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
f.Close()
|
|
|
|
}
|
2020-06-24 03:07:25 +03:00
|
|
|
// TOFU
|
2020-06-22 00:35:19 +03:00
|
|
|
err = os.MkdirAll(tofuDBDir, 0755)
|
2020-06-18 23:54:48 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-08-07 19:27:50 +03:00
|
|
|
f, err = os.OpenFile(tofuDBPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
|
|
|
|
if err == nil {
|
|
|
|
f.Close()
|
|
|
|
}
|
2020-06-24 03:07:25 +03:00
|
|
|
// Bookmarks
|
|
|
|
err = os.MkdirAll(bkmkDir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-02-27 08:13:11 +03:00
|
|
|
// OldBkmkPath isn't created because it shouldn't be there anyway
|
|
|
|
|
2020-08-11 01:50:40 +03:00
|
|
|
// Feeds
|
2020-11-28 01:01:29 +03:00
|
|
|
err = os.MkdirAll(subscriptionDir, 0755)
|
2020-08-11 01:50:40 +03:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-06-24 03:07:25 +03:00
|
|
|
|
2020-08-07 19:27:50 +03:00
|
|
|
// *** Setup vipers ***
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2020-06-22 00:35:19 +03:00
|
|
|
TofuStore.SetConfigFile(tofuDBPath)
|
2020-06-18 23:54:48 +03:00
|
|
|
TofuStore.SetConfigType("toml")
|
|
|
|
err = TofuStore.ReadInConfig()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2021-02-27 08:13:11 +03:00
|
|
|
BkmkStore.SetConfigFile(OldBkmkPath)
|
2020-06-24 03:07:25 +03:00
|
|
|
BkmkStore.SetConfigType("toml")
|
|
|
|
err = BkmkStore.ReadInConfig()
|
|
|
|
if err != nil {
|
2021-02-27 08:13:11 +03:00
|
|
|
// File doesn't exist, so remove the viper
|
|
|
|
BkmkStore = nil
|
2020-06-24 03:07:25 +03:00
|
|
|
}
|
|
|
|
|
2020-08-07 19:27:50 +03:00
|
|
|
// Setup main config
|
|
|
|
|
2020-12-20 23:54:47 +03:00
|
|
|
viper.SetDefault("a-general.home", "gemini://gemini.circumlunar.space")
|
2020-08-28 01:55:42 +03:00
|
|
|
viper.SetDefault("a-general.auto_redirect", false)
|
2020-06-18 23:54:48 +03:00
|
|
|
viper.SetDefault("a-general.http", "default")
|
2021-03-08 22:23:49 +03:00
|
|
|
viper.SetDefault("a-general.search", "gemini://geminispace.info/search")
|
2020-06-18 23:54:48 +03:00
|
|
|
viper.SetDefault("a-general.color", true)
|
2020-09-04 19:42:01 +03:00
|
|
|
viper.SetDefault("a-general.ansi", true)
|
2021-12-11 07:09:31 +03:00
|
|
|
viper.SetDefault("a-general.highlight_code", true)
|
|
|
|
viper.SetDefault("a-general.highlight_style", "monokai")
|
2020-06-18 23:54:48 +03:00
|
|
|
viper.SetDefault("a-general.bullets", true)
|
2020-12-01 22:00:01 +03:00
|
|
|
viper.SetDefault("a-general.show_link", false)
|
2021-12-23 04:36:12 +03:00
|
|
|
viper.SetDefault("a-general.max_width", 80)
|
2020-07-10 02:28:39 +03:00
|
|
|
viper.SetDefault("a-general.downloads", "")
|
2020-12-14 22:28:07 +03:00
|
|
|
viper.SetDefault("a-general.temp_downloads", "")
|
2020-07-10 22:33:39 +03:00
|
|
|
viper.SetDefault("a-general.page_max_size", 2097152)
|
|
|
|
viper.SetDefault("a-general.page_max_time", 10)
|
2021-02-17 22:17:13 +03:00
|
|
|
viper.SetDefault("a-general.scrollbar", "auto")
|
2021-12-03 19:45:36 +03:00
|
|
|
viper.SetDefault("a-general.underline", true)
|
2020-12-25 00:13:38 +03:00
|
|
|
viper.SetDefault("keybindings.bind_reload", []string{"R", "Ctrl-R"})
|
|
|
|
viper.SetDefault("keybindings.bind_home", "Backspace")
|
|
|
|
viper.SetDefault("keybindings.bind_bookmarks", "Ctrl-B")
|
|
|
|
viper.SetDefault("keybindings.bind_add_bookmark", "Ctrl-D")
|
|
|
|
viper.SetDefault("keybindings.bind_sub", "Ctrl-A")
|
|
|
|
viper.SetDefault("keybindings.bind_add_sub", "Ctrl-X")
|
|
|
|
viper.SetDefault("keybindings.bind_save", "Ctrl-S")
|
2021-04-22 04:59:05 +03:00
|
|
|
viper.SetDefault("keybindings.bind_moveup", "k")
|
|
|
|
viper.SetDefault("keybindings.bind_movedown", "j")
|
|
|
|
viper.SetDefault("keybindings.bind_moveleft", "h")
|
|
|
|
viper.SetDefault("keybindings.bind_moveright", "l")
|
2020-12-25 00:13:38 +03:00
|
|
|
viper.SetDefault("keybindings.bind_pgup", []string{"PgUp", "u"})
|
|
|
|
viper.SetDefault("keybindings.bind_pgdn", []string{"PgDn", "d"})
|
|
|
|
viper.SetDefault("keybindings.bind_bottom", "Space")
|
|
|
|
viper.SetDefault("keybindings.bind_edit", "e")
|
|
|
|
viper.SetDefault("keybindings.bind_back", []string{"b", "Alt-Left"})
|
|
|
|
viper.SetDefault("keybindings.bind_forward", []string{"f", "Alt-Right"})
|
|
|
|
viper.SetDefault("keybindings.bind_new_tab", "Ctrl-T")
|
|
|
|
viper.SetDefault("keybindings.bind_close_tab", "Ctrl-W")
|
|
|
|
viper.SetDefault("keybindings.bind_next_tab", "F2")
|
|
|
|
viper.SetDefault("keybindings.bind_prev_tab", "F1")
|
2022-02-05 00:05:16 +03:00
|
|
|
viper.SetDefault("keybindings.bind_quit", []string{"Ctrl-C", "Ctrl-Q", "Q"})
|
2020-12-25 00:13:38 +03:00
|
|
|
viper.SetDefault("keybindings.bind_help", "?")
|
|
|
|
viper.SetDefault("keybindings.bind_link1", "1")
|
|
|
|
viper.SetDefault("keybindings.bind_link2", "2")
|
|
|
|
viper.SetDefault("keybindings.bind_link3", "3")
|
|
|
|
viper.SetDefault("keybindings.bind_link4", "4")
|
|
|
|
viper.SetDefault("keybindings.bind_link5", "5")
|
|
|
|
viper.SetDefault("keybindings.bind_link6", "6")
|
|
|
|
viper.SetDefault("keybindings.bind_link7", "7")
|
|
|
|
viper.SetDefault("keybindings.bind_link8", "8")
|
|
|
|
viper.SetDefault("keybindings.bind_link9", "9")
|
|
|
|
viper.SetDefault("keybindings.bind_link0", "0")
|
|
|
|
viper.SetDefault("keybindings.bind_tab1", "!")
|
|
|
|
viper.SetDefault("keybindings.bind_tab2", "@")
|
|
|
|
viper.SetDefault("keybindings.bind_tab3", "#")
|
|
|
|
viper.SetDefault("keybindings.bind_tab4", "$")
|
|
|
|
viper.SetDefault("keybindings.bind_tab5", "%")
|
|
|
|
viper.SetDefault("keybindings.bind_tab6", "^")
|
|
|
|
viper.SetDefault("keybindings.bind_tab7", "&")
|
|
|
|
viper.SetDefault("keybindings.bind_tab8", "*")
|
|
|
|
viper.SetDefault("keybindings.bind_tab9", "(")
|
|
|
|
viper.SetDefault("keybindings.bind_tab0", ")")
|
2021-04-21 00:00:34 +03:00
|
|
|
viper.SetDefault("keybindings.bind_copy_page_url", "C")
|
|
|
|
viper.SetDefault("keybindings.bind_copy_target_url", "c")
|
2021-05-15 01:09:04 +03:00
|
|
|
viper.SetDefault("keybindings.bind_beginning", []string{"Home", "g"})
|
|
|
|
viper.SetDefault("keybindings.bind_end", []string{"End", "G"})
|
2020-12-25 00:13:38 +03:00
|
|
|
viper.SetDefault("keybindings.shift_numbers", "")
|
2021-12-29 01:35:08 +03:00
|
|
|
viper.SetDefault("keybindings.bind_url_handler_open", "Ctrl-U")
|
2021-12-07 23:28:34 +03:00
|
|
|
viper.SetDefault("url-handlers.other", "default")
|
2020-06-18 23:54:48 +03:00
|
|
|
viper.SetDefault("cache.max_size", 0)
|
|
|
|
viper.SetDefault("cache.max_pages", 20)
|
2020-12-20 23:54:47 +03:00
|
|
|
viper.SetDefault("cache.timeout", 1800)
|
2020-11-28 01:01:29 +03:00
|
|
|
viper.SetDefault("subscriptions.popup", true)
|
|
|
|
viper.SetDefault("subscriptions.update_interval", 1800)
|
|
|
|
viper.SetDefault("subscriptions.workers", 3)
|
2020-12-07 04:57:57 +03:00
|
|
|
viper.SetDefault("subscriptions.entries_per_page", 20)
|
2021-12-23 22:18:18 +03:00
|
|
|
viper.SetDefault("subscriptions.header", true)
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2020-06-22 00:35:19 +03:00
|
|
|
viper.SetConfigFile(configPath)
|
2020-06-18 23:54:48 +03:00
|
|
|
viper.SetConfigType("toml")
|
|
|
|
err = viper.ReadInConfig()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2020-12-25 00:13:38 +03:00
|
|
|
// Setup the key bindings
|
|
|
|
KeyInit()
|
|
|
|
|
2020-12-20 23:23:00 +03:00
|
|
|
// *** Downloads paths, setup, and creation ***
|
|
|
|
|
|
|
|
// Setup downloads dir
|
|
|
|
if viper.GetString("a-general.downloads") == "" {
|
|
|
|
// Find default Downloads dir
|
|
|
|
if userdirs.Download == "" {
|
|
|
|
DownloadsDir = filepath.Join(home, "Downloads")
|
|
|
|
} else {
|
|
|
|
DownloadsDir = userdirs.Download
|
|
|
|
}
|
|
|
|
// Create it just in case
|
|
|
|
err = os.MkdirAll(DownloadsDir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("downloads path could not be created: %s", DownloadsDir)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Validate path
|
|
|
|
dDir := viper.GetString("a-general.downloads")
|
|
|
|
di, err := os.Stat(dDir)
|
|
|
|
if err == nil {
|
|
|
|
if !di.IsDir() {
|
|
|
|
return fmt.Errorf("downloads path specified is not a directory: %s", dDir)
|
|
|
|
}
|
|
|
|
} else if os.IsNotExist(err) {
|
|
|
|
// Try to create path
|
|
|
|
err = os.MkdirAll(dDir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("downloads path could not be created: %s", dDir)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Some other error
|
|
|
|
return fmt.Errorf("couldn't access downloads directory: %s", dDir)
|
|
|
|
}
|
|
|
|
DownloadsDir = dDir
|
|
|
|
}
|
|
|
|
|
2020-12-25 00:54:06 +03:00
|
|
|
// Setup temporary downloads dir
|
|
|
|
if viper.GetString("a-general.temp_downloads") == "" {
|
|
|
|
TempDownloadsDir = filepath.Join(os.TempDir(), "amfora_temp")
|
|
|
|
|
|
|
|
// Make sure it exists
|
|
|
|
err = os.MkdirAll(TempDownloadsDir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("temp downloads path could not be created: %s", TempDownloadsDir)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Validate path
|
|
|
|
dDir := viper.GetString("a-general.temp_downloads")
|
|
|
|
di, err := os.Stat(dDir)
|
|
|
|
if err == nil {
|
|
|
|
if !di.IsDir() {
|
|
|
|
return fmt.Errorf("temp downloads path specified is not a directory: %s", dDir)
|
|
|
|
}
|
|
|
|
} else if os.IsNotExist(err) {
|
|
|
|
// Try to create path
|
|
|
|
err = os.MkdirAll(dDir, 0755)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("temp downloads path could not be created: %s", dDir)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Some other error
|
|
|
|
return fmt.Errorf("couldn't access temp downloads directory: %s", dDir)
|
|
|
|
}
|
|
|
|
TempDownloadsDir = dDir
|
|
|
|
}
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
// Setup cache from config
|
|
|
|
cache.SetMaxSize(viper.GetInt("cache.max_size"))
|
|
|
|
cache.SetMaxPages(viper.GetInt("cache.max_pages"))
|
2020-12-20 23:54:47 +03:00
|
|
|
cache.SetTimeout(viper.GetInt("cache.timeout"))
|
2020-06-18 23:54:48 +03:00
|
|
|
|
2021-12-29 03:43:24 +03:00
|
|
|
setColor := func(k string, colorStr string) error {
|
2022-01-02 21:30:46 +03:00
|
|
|
if k == "include" {
|
|
|
|
return nil
|
|
|
|
}
|
2021-12-29 03:43:24 +03:00
|
|
|
colorStr = strings.ToLower(colorStr)
|
|
|
|
var color tcell.Color
|
|
|
|
if colorStr == "default" {
|
|
|
|
if strings.HasSuffix(k, "bg") {
|
|
|
|
color = tcell.ColorDefault
|
|
|
|
} else {
|
|
|
|
return fmt.Errorf(`"default" is only valid for a background color (color ending in "bg"), not "%s"`, k)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
color = tcell.GetColor(colorStr)
|
|
|
|
if color == tcell.ColorDefault {
|
|
|
|
return fmt.Errorf(`invalid color format for "%s": %s`, k, colorStr)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SetColor(k, color)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-08-07 19:27:50 +03:00
|
|
|
// Setup theme
|
2020-07-28 23:58:32 +03:00
|
|
|
configTheme := viper.Sub("theme")
|
|
|
|
if configTheme != nil {
|
2021-12-29 03:43:24 +03:00
|
|
|
// Include key comes first
|
|
|
|
if incPath := configTheme.GetString("include"); incPath != "" {
|
|
|
|
incViper := viper.New()
|
2022-04-26 02:54:17 +03:00
|
|
|
newIncPath, err := homedir.Expand(incPath)
|
|
|
|
if err == nil {
|
|
|
|
incViper.SetConfigFile(newIncPath)
|
|
|
|
} else {
|
|
|
|
incViper.SetConfigFile(incPath)
|
|
|
|
}
|
2021-12-29 03:43:24 +03:00
|
|
|
incViper.SetConfigType("toml")
|
|
|
|
err = incViper.ReadInConfig()
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
for k2, v2 := range incViper.AllSettings() {
|
|
|
|
colorStr, ok := v2.(string)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf(`include: value for "%s" is not a string: %v`, k2, v2)
|
|
|
|
}
|
2021-12-29 20:06:40 +03:00
|
|
|
if err := setColor(k2, colorStr); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2021-12-29 03:43:24 +03:00
|
|
|
}
|
|
|
|
}
|
2020-07-28 23:58:32 +03:00
|
|
|
for k, v := range configTheme.AllSettings() {
|
|
|
|
colorStr, ok := v.(string)
|
|
|
|
if !ok {
|
|
|
|
return fmt.Errorf(`value for "%s" is not a string: %v`, k, v)
|
|
|
|
}
|
2021-12-29 20:06:40 +03:00
|
|
|
if err := setColor(k, colorStr); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2020-07-28 23:58:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if viper.GetBool("a-general.color") {
|
|
|
|
cview.Styles.PrimitiveBackgroundColor = GetColor("bg")
|
2021-12-04 01:58:16 +03:00
|
|
|
} else {
|
2021-12-04 02:02:10 +03:00
|
|
|
// No colors allowed, set background to black instead of default
|
2021-12-04 01:58:16 +03:00
|
|
|
themeMu.Lock()
|
|
|
|
theme["bg"] = tcell.ColorBlack
|
|
|
|
cview.Styles.PrimitiveBackgroundColor = tcell.ColorBlack
|
2021-12-04 04:52:30 +03:00
|
|
|
themeMu.Unlock()
|
2021-12-04 01:58:16 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
hasDarkTerminalBackground = termenv.HasDarkBackground()
|
2020-07-28 23:58:32 +03:00
|
|
|
|
2020-11-05 02:35:56 +03:00
|
|
|
// Parse HTTP command
|
2020-11-05 02:47:27 +03:00
|
|
|
HTTPCommand = viper.GetStringSlice("a-general.http")
|
|
|
|
if len(HTTPCommand) == 0 {
|
2020-11-05 02:35:56 +03:00
|
|
|
// Not a string array, interpret as a string instead
|
|
|
|
// Split on spaces to maintain compatibility with old versions
|
|
|
|
// The new better way to is to just define a string array in config
|
2020-11-05 02:47:27 +03:00
|
|
|
HTTPCommand = strings.Fields(viper.GetString("a-general.http"))
|
2020-11-05 02:35:56 +03:00
|
|
|
}
|
|
|
|
|
2020-12-14 22:28:07 +03:00
|
|
|
var rawMediaHandlers []struct {
|
|
|
|
Cmd []string `mapstructure:"cmd"`
|
|
|
|
Types []string `mapstructure:"types"`
|
|
|
|
NoPrompt bool `mapstructure:"no_prompt"`
|
2020-12-25 07:38:12 +03:00
|
|
|
Stream bool `mapstructure:"stream"`
|
2020-12-14 22:28:07 +03:00
|
|
|
}
|
|
|
|
err = viper.UnmarshalKey("mediatype-handlers", &rawMediaHandlers)
|
|
|
|
if err != nil {
|
|
|
|
return fmt.Errorf("couldn't parse mediatype-handlers section in config: %w", err)
|
|
|
|
}
|
|
|
|
for _, rawMediaHandler := range rawMediaHandlers {
|
2020-12-25 07:38:12 +03:00
|
|
|
if len(rawMediaHandler.Cmd) == 0 {
|
|
|
|
return fmt.Errorf("empty cmd array in mediatype-handlers section")
|
|
|
|
}
|
|
|
|
if len(rawMediaHandler.Types) == 0 {
|
|
|
|
return fmt.Errorf("empty types array in mediatype-handlers section")
|
|
|
|
}
|
|
|
|
|
2020-12-14 22:28:07 +03:00
|
|
|
for _, typ := range rawMediaHandler.Types {
|
|
|
|
if _, ok := MediaHandlers[typ]; ok {
|
|
|
|
return fmt.Errorf("multiple mediatype-handlers defined for %v", typ)
|
|
|
|
}
|
|
|
|
MediaHandlers[typ] = MediaHandler{
|
|
|
|
Cmd: rawMediaHandler.Cmd,
|
|
|
|
NoPrompt: rawMediaHandler.NoPrompt,
|
2020-12-25 07:38:12 +03:00
|
|
|
Stream: rawMediaHandler.Stream,
|
2020-12-14 22:28:07 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-17 22:17:13 +03:00
|
|
|
// Parse scrollbar options
|
|
|
|
switch viper.GetString("a-general.scrollbar") {
|
|
|
|
case "never":
|
|
|
|
ScrollBar = cview.ScrollBarNever
|
|
|
|
case "always":
|
|
|
|
ScrollBar = cview.ScrollBarAlways
|
|
|
|
default:
|
|
|
|
ScrollBar = cview.ScrollBarAuto
|
|
|
|
}
|
|
|
|
|
2020-06-18 23:54:48 +03:00
|
|
|
return nil
|
|
|
|
}
|