Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Marquee decorator for long message scrolling #126

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

DeathKing
Copy link

2023-03-22-231235

Add Marquee decorator that scrolls text from right to
left, it is useful when displaying long messages. The codes are not carefully written, modifications are welcomed.

@vbauerster
Copy link
Owner

Implementation assumes that (string width = bytes width), therefore it's going to fail with non Latin strings. Try it for example with Россия великая страна! string to see what I mean.

@DeathKing
Copy link
Author

@vbauerster Da, I know what you mean, I noticed that issue too. After opened this PR and some investigation of mpb source code, I found the go-runewidth library that you used may be the solution.

I implement this feature in my project like this (https://github.com/DeathKing/pico/blob/master/cmd/pdf2image/bar.go#L14-L28):

func Marquee(textGetter func() string, ws uint, wcc ...decor.WC) decor.Decorator {
	var count uint
	f := func(s decor.Statistics) string {
		text := textGetter()
		runes := []rune(text)

		msg := string(runes[int(count)%len(runes):])
		count++

		return runewidth.FillRight(
			runewidth.Truncate(msg, int(ws), ""),
			int(ws))
	}
	return decor.Any(f, wcc...)
}
bar.mov

For this specific implementation, the API requires a getter function to obtain the text for display, which may not suitable for most case, a string parameter should be used instead as I suppose.

I'd like to know your opinion about this feature.

@RikaCelery
Copy link

Try this?🤔
It works well for me.

func Marquee(t string, ws int, divider string, wcc ...decor.WC) decor.Decorator {
	var count int
	var f = func(s decor.Statistics) string {
		length := runewidth.StringWidth(t + divider)
		if runewidth.StringWidth(t) < ws {
			return runewidth.FillRight(t, ws)
		}
		text := t + divider
		var msg string

		if count-ws > length {
			msg = TruncateLeft(Truncate(text, count+ws), ws)
		} else {
			msg = TruncateLeft(Truncate(text, count+ws), count)
		}
		if count+ws > length {
			msg += Truncate(text, count+ws-length)
		}
		count++
		if count+ws >= len(t)+len(divider)-1 {
			count = 0
		}
		return runewidth.FillRight(msg, ws)
	}
	return decor.Any(f, wcc...)
}

func Truncate(s string, size int) string {
	return runewidth.Truncate(s, size, "")
}
func TruncateLeft(s string, size int) string {
	return runewidth.TruncateLeft(s, size, "")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants