From da06d5ef1446eb99ad4a4c3df0a96ea29a0a0f84 Mon Sep 17 00:00:00 2001 From: Simon Roberts Date: Tue, 12 Oct 2021 16:57:04 +1100 Subject: [PATCH 1/2] Remove fallback to coin.Symbol when loading portfolio. Remove deprecated favoritesBySymbol. (#219) * Remove fallback to coin.Symbol when loading portfolio (use coin.Name) * Remove deprecated favoritesBySymbol --- cointop/cointop.go | 32 ++++++-------------------------- cointop/config.go | 10 ---------- cointop/portfolio.go | 12 ++++-------- 3 files changed, 10 insertions(+), 44 deletions(-) diff --git a/cointop/cointop.go b/cointop/cointop.go index ca3afec..2f08e1f 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -48,9 +48,6 @@ type State struct { defaultChartRange string maxChartWidth int - // DEPRECATED: favorites by 'symbol' is deprecated because of collisions. - favoritesBySymbol map[string]bool - favorites map[string]bool favoritesTableColumns []string favoriteChar string @@ -259,14 +256,12 @@ func NewCointop(config *Config) (*Cointop, error) { limiter: time.NewTicker(2 * time.Second).C, filecache: nil, State: &State{ - allCoins: []*Coin{}, - cacheDir: DefaultCacheDir, - coinsTableColumns: DefaultCoinTableHeaders, - currencyConversion: DefaultCurrency, - defaultChartRange: DefaultChartRange, - maxChartWidth: DefaultMaxChartWidth, - // DEPRECATED: favorites by 'symbol' is deprecated because of collisions. Kept for backward compatibility. - favoritesBySymbol: make(map[string]bool), + allCoins: []*Coin{}, + cacheDir: DefaultCacheDir, + coinsTableColumns: DefaultCoinTableHeaders, + currencyConversion: DefaultCurrency, + defaultChartRange: DefaultChartRange, + maxChartWidth: DefaultMaxChartWidth, favorites: make(map[string]bool), favoritesTableColumns: DefaultCoinTableHeaders, favoriteChar: DefaultFavoriteChar, @@ -454,21 +449,6 @@ func NewCointop(config *Config) (*Cointop, error) { ct.State.coins = ct.State.allCoins[0:max] } - // DEPRECATED: favorites by 'symbol' is deprecated because of collisions. Kept for backward compatibility. - // Here we're doing a lookup based on symbol and setting the favorite to the coin name instead of coin symbol. - ct.State.allCoinsSlugMap.Range(func(key, value interface{}) bool { - if coin, ok := value.(*Coin); ok { - for k := range ct.State.favoritesBySymbol { - if coin.Symbol == k { - ct.State.favorites[coin.Name] = true - delete(ct.State.favoritesBySymbol, k) - } - } - } - - return true - }) - var globaldata []float64 chartcachekey := ct.CompositeCacheKey("globaldata", "", "", ct.State.selectedChartRange) if ct.filecache != nil { diff --git a/cointop/config.go b/cointop/config.go index dbe1f94..58c467e 100644 --- a/cointop/config.go +++ b/cointop/config.go @@ -214,10 +214,7 @@ func (ct *Cointop) ConfigToToml() ([]byte, error) { return favoritesIfc[i].(string) < favoritesIfc[j].(string) }) - var favoritesBySymbolIfc []interface{} favoritesMapIfc := map[string]interface{}{ - // DEPRECATED: favorites by 'symbol' is deprecated because of collisions. Kept for backward compatibility. - "symbols": favoritesBySymbolIfc, "names": favoritesIfc, "columns": ct.State.favoritesTableColumns, "character": ct.State.favoriteChar, @@ -509,13 +506,6 @@ func (ct *Cointop) loadFavoritesFromConfig() error { continue } switch k { - // DEPRECATED: favorites by 'symbol' is deprecated because of collisions. Kept for backward compatibility. - case "symbols": - for _, ifc := range ifcs { - if v, ok := ifc.(string); ok { - ct.State.favoritesBySymbol[strings.ToUpper(v)] = true - } - } case "names": for _, ifc := range ifcs { if v, ok := ifc.(string); ok { diff --git a/cointop/portfolio.go b/cointop/portfolio.go index 89f6077..d27f32f 100644 --- a/cointop/portfolio.go +++ b/cointop/portfolio.go @@ -492,15 +492,11 @@ func (ct *Cointop) PortfolioEntry(c *Coin) (*PortfolioEntry, bool) { var ok bool key := strings.ToLower(c.Name) if p, ok = ct.State.portfolio.Entries[key]; !ok { - // NOTE: if not found then try the symbol - key := strings.ToLower(c.Symbol) - if p, ok = ct.State.portfolio.Entries[key]; !ok { - p = &PortfolioEntry{ - Coin: c.Name, - Holdings: 0, - } - isNew = true + p = &PortfolioEntry{ + Coin: c.Name, + Holdings: 0, } + isNew = true } return p, isNew From e409a0bddee50cd4015357959d706a7aa7f8aeef Mon Sep 17 00:00:00 2001 From: Simon Roberts Date: Tue, 12 Oct 2021 17:11:14 +1100 Subject: [PATCH 2/2] Improvements to search mechanism (#216) * Enable repeated search using empty search expression (`/` then ``) * Quick note about how to repeat-search in the FAQ --- cointop/cointop.go | 1 + cointop/search.go | 25 ++++++++++++++++++++++--- docs/content/faq.md | 1 + 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/cointop/cointop.go b/cointop/cointop.go index 2f08e1f..4b15410 100644 --- a/cointop/cointop.go +++ b/cointop/cointop.go @@ -69,6 +69,7 @@ type State struct { refreshRate time.Duration running bool searchFieldVisible bool + lastSearchQuery string selectedCoin *Coin selectedChartRange string selectedView string diff --git a/cointop/search.go b/cointop/search.go index 9643cce..dd06844 100644 --- a/cointop/search.go +++ b/cointop/search.go @@ -66,7 +66,7 @@ func (ct *Cointop) DoSearch() error { if n == 0 { return nil } - q := string(b) + q := strings.TrimSpace(string(b[:n])) // remove slash regex := regexp.MustCompile(`/(.*)`) matches := regex.FindStringSubmatch(q) @@ -78,13 +78,32 @@ func (ct *Cointop) DoSearch() error { // Search performs the search and filtering func (ct *Cointop) Search(q string) error { - log.Debug("Search()") + log.Debugf("Search(%s)", q) + + // If there are no coins, return no result + if len(ct.State.coins) == 0 { + return nil + } + + // If search term is empty, use the previous search term. q = strings.TrimSpace(strings.ToLower(q)) + if q == "" { + q = ct.State.lastSearchQuery + } else { + ct.State.lastSearchQuery = q + } + idx := -1 min := -1 var hasprefixidx []int var hasprefixdist []int - for i := range ct.State.allCoins { + + // Start the search from the current position (+1), looking names that start with the search term, or symbols that match completely + currentIndex := ct.GetGlobalCoinIndex(ct.HighlightedRowCoin()) + 1 + if ct.IsLastPage() && ct.IsLastRow() { + currentIndex = 0 + } + for i := currentIndex; i < len(ct.State.allCoins); i++ { coin := ct.State.allCoins[i] name := strings.ToLower(coin.Name) symbol := strings.ToLower(coin.Symbol) diff --git a/docs/content/faq.md b/docs/content/faq.md index 8a700a2..1ee7e20 100644 --- a/docs/content/faq.md +++ b/docs/content/faq.md @@ -132,6 +132,7 @@ draft: false ## How do I search? The default key to open search is /. Type the search query after the `/` in the field and hit Enter. + Each search starts from the current cursor position. To search for the same term again, hit / then Enter. ## How do I exit search?