-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[protip] Added new package for showing usage tips
- Loading branch information
Showing
6 changed files
with
239 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ L + netutil | |
* + pid | ||
* + pluralize | ||
* + progress | ||
* + protip | ||
* + rand | ||
* + req | ||
* + secstr | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package protip | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
// // | ||
// Copyright (c) 2023 ESSENTIAL KAOS // | ||
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> // | ||
// // | ||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func ExampleAdd() { | ||
// Add simple tip | ||
Add(&Tip{ | ||
Title: "Tip #1", | ||
Message: `Tip message`, | ||
}) | ||
|
||
// Add tip with custom weight (≠ 0.5) | ||
Add(&Tip{ | ||
Title: "Tip #2", | ||
Message: `Tip message`, | ||
Weight: 0.1, | ||
}) | ||
|
||
// Add tip with custom weight (≠ 0.5) and color | ||
Add(&Tip{ | ||
Title: "Tip #3", | ||
Message: `Tip message`, | ||
Weight: 0.8, | ||
ColorTag: "{b}", | ||
}) | ||
} | ||
|
||
func ExampleShow() { | ||
// Add simple tip | ||
Add(&Tip{ | ||
Title: "Tip #1", | ||
Message: `Tip message`, | ||
}) | ||
|
||
// Increase default probability to 50% | ||
Probability = 0.5 | ||
|
||
// Set default color to green | ||
ColorTag = "{g}" | ||
|
||
// Try to show tip | ||
Show(false) | ||
|
||
// Force show | ||
Show(true) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
// Package protip provides methods for displaying usage tips | ||
package protip | ||
|
||
import ( | ||
"math/rand" | ||
|
||
"github.com/essentialkaos/ek/v12/fmtc" | ||
"github.com/essentialkaos/ek/v12/fmtutil/panel" | ||
"github.com/essentialkaos/ek/v12/strutil" | ||
) | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// Tip contains basic tip content | ||
type Tip struct { | ||
Title string // Tip title (required) | ||
Message string // Tip message (required) | ||
|
||
ColorTag string // Custom tip color (optional) | ||
Weight float64 // Custom tip weight (optional) | ||
} | ||
|
||
// Tips contains tips data | ||
type Tips struct { | ||
data []*Tip | ||
selectors []int | ||
maxWeight int | ||
} | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// Probability is showing probability coefficient (0 ← less | more → 1) | ||
var Probability = 0.25 | ||
|
||
// ColorTag is default panel color tag | ||
var ColorTag = "{#75}" | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
var collection *Tips | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// Add adds one or more tips to collection | ||
func Add(tips ...*Tip) { | ||
if collection == nil { | ||
collection = &Tips{} | ||
} | ||
|
||
for _, tip := range tips { | ||
if tip == nil || tip.Title == "" || | ||
tip.Message == "" || !fmtc.IsTag(tip.ColorTag) { | ||
continue | ||
} | ||
|
||
if tip.Weight == 0 { | ||
tip.Weight = 0.5 | ||
} | ||
|
||
collection.data = append(collection.data, tip) | ||
} | ||
} | ||
|
||
// Show shows random tip if required | ||
func Show(force bool) bool { | ||
if collection == nil || len(collection.data) == 0 { | ||
return false | ||
} | ||
|
||
if rand.Float64() > Probability && !force { | ||
return false | ||
} | ||
|
||
if len(collection.selectors) != len(collection.data) { | ||
collection.selectors = make([]int, len(collection.data)) | ||
collection.maxWeight = 0 | ||
|
||
for i, tip := range collection.data { | ||
collection.maxWeight += int(tip.Weight * 100) | ||
collection.selectors[i] = collection.maxWeight | ||
} | ||
} | ||
|
||
rnd := rand.Intn(collection.maxWeight) + 1 | ||
index := searchInts(collection.selectors, rnd) | ||
tip := collection.data[index] | ||
|
||
color := strutil.Q(tip.ColorTag, ColorTag) | ||
color = strutil.B(fmtc.IsTag(color), color, "{#75}") | ||
|
||
panel.Panel( | ||
"❏ PROTIP", color, tip.Title, tip.Message, | ||
panel.BOTTOM_LINE, panel.TOP_LINE, panel.INDENT_OUTER, | ||
) | ||
|
||
return true | ||
} | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
// searchInts improved searchInts version | ||
// | ||
// Original: https://github.com/mroth/weightedrand | ||
func searchInts(a []int, x int) int { | ||
var i int | ||
|
||
j := len(a) | ||
|
||
for i < j { | ||
h := int(uint(i+j) >> 1) | ||
|
||
if a[h] < x { | ||
i = h + 1 | ||
} else { | ||
j = h | ||
} | ||
} | ||
|
||
return i | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package protip | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
// // | ||
// Copyright (c) 2023 ESSENTIAL KAOS // | ||
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> // | ||
// // | ||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/essentialkaos/check" | ||
) | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func Test(t *testing.T) { TestingT(t) } | ||
|
||
type TipSuite struct{} | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
var _ = Suite(&TipSuite{}) | ||
|
||
// ////////////////////////////////////////////////////////////////////////////////// // | ||
|
||
func (s *TipSuite) TestAdd(c *C) { | ||
c.Assert(collection, IsNil) | ||
|
||
var tip *Tip | ||
Add(tip) | ||
c.Assert(collection, NotNil) | ||
c.Assert(collection.data, HasLen, 0) | ||
|
||
tip = &Tip{} | ||
Add(tip) | ||
c.Assert(collection.data, HasLen, 0) | ||
|
||
tip.Title = "TEST" | ||
Add(tip) | ||
c.Assert(collection.data, HasLen, 0) | ||
|
||
tip.Message = "Test message" | ||
Add(tip) | ||
c.Assert(collection.data, HasLen, 1) | ||
c.Assert(collection.data[0].Weight, Equals, 0.5) | ||
} | ||
|
||
func (s *TipSuite) TestShow(c *C) { | ||
collection = nil | ||
|
||
c.Assert(Show(true), Equals, false) | ||
|
||
Add(&Tip{Title: "Test #1", Message: "Test", Weight: 0.99, ColorTag: "{r}"}) | ||
Add(&Tip{Title: "Test #2", Message: "Test", Weight: 0.01}) | ||
|
||
Probability = 0.0 | ||
|
||
c.Assert(Show(false), Equals, false) | ||
|
||
Probability = 1.0 | ||
|
||
c.Assert(Show(true), Equals, true) | ||
} |