Skip to content

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.

3 participants