mirror of
				https://github.com/fluffle/goirc
				synced 2025-11-03 19:48:04 +00:00 
			
		
		
		
	Make split marker configurable; tests.
This commit is contained in:
		
							parent
							
								
									53eac75162
								
							
						
					
					
						commit
						de089e2f58
					
				
					 3 changed files with 80 additions and 54 deletions
				
			
		| 
						 | 
				
			
			@ -6,36 +6,37 @@ import (
 | 
			
		|||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	REGISTER     = "REGISTER"
 | 
			
		||||
	CONNECTED    = "CONNECTED"
 | 
			
		||||
	DISCONNECTED = "DISCONNECTED"
 | 
			
		||||
	ACTION       = "ACTION"
 | 
			
		||||
	AUTHENTICATE = "AUTHENTICATE"
 | 
			
		||||
	AWAY         = "AWAY"
 | 
			
		||||
	CAP          = "CAP"
 | 
			
		||||
	CTCP         = "CTCP"
 | 
			
		||||
	CTCPREPLY    = "CTCPREPLY"
 | 
			
		||||
	ERROR        = "ERROR"
 | 
			
		||||
	INVITE       = "INVITE"
 | 
			
		||||
	JOIN         = "JOIN"
 | 
			
		||||
	KICK         = "KICK"
 | 
			
		||||
	MODE         = "MODE"
 | 
			
		||||
	NICK         = "NICK"
 | 
			
		||||
	NOTICE       = "NOTICE"
 | 
			
		||||
	OPER         = "OPER"
 | 
			
		||||
	PART         = "PART"
 | 
			
		||||
	PASS         = "PASS"
 | 
			
		||||
	PING         = "PING"
 | 
			
		||||
	PONG         = "PONG"
 | 
			
		||||
	PRIVMSG      = "PRIVMSG"
 | 
			
		||||
	QUIT         = "QUIT"
 | 
			
		||||
	TOPIC        = "TOPIC"
 | 
			
		||||
	USER         = "USER"
 | 
			
		||||
	VERSION      = "VERSION"
 | 
			
		||||
	VHOST        = "VHOST"
 | 
			
		||||
	WHO          = "WHO"
 | 
			
		||||
	WHOIS        = "WHOIS"
 | 
			
		||||
	defaultSplit = 450
 | 
			
		||||
	REGISTER      = "REGISTER"
 | 
			
		||||
	CONNECTED     = "CONNECTED"
 | 
			
		||||
	DISCONNECTED  = "DISCONNECTED"
 | 
			
		||||
	ACTION        = "ACTION"
 | 
			
		||||
	AUTHENTICATE  = "AUTHENTICATE"
 | 
			
		||||
	AWAY          = "AWAY"
 | 
			
		||||
	CAP           = "CAP"
 | 
			
		||||
	CTCP          = "CTCP"
 | 
			
		||||
	CTCPREPLY     = "CTCPREPLY"
 | 
			
		||||
	ERROR         = "ERROR"
 | 
			
		||||
	INVITE        = "INVITE"
 | 
			
		||||
	JOIN          = "JOIN"
 | 
			
		||||
	KICK          = "KICK"
 | 
			
		||||
	MODE          = "MODE"
 | 
			
		||||
	NICK          = "NICK"
 | 
			
		||||
	NOTICE        = "NOTICE"
 | 
			
		||||
	OPER          = "OPER"
 | 
			
		||||
	PART          = "PART"
 | 
			
		||||
	PASS          = "PASS"
 | 
			
		||||
	PING          = "PING"
 | 
			
		||||
	PONG          = "PONG"
 | 
			
		||||
	PRIVMSG       = "PRIVMSG"
 | 
			
		||||
	QUIT          = "QUIT"
 | 
			
		||||
	TOPIC         = "TOPIC"
 | 
			
		||||
	USER          = "USER"
 | 
			
		||||
	VERSION       = "VERSION"
 | 
			
		||||
	VHOST         = "VHOST"
 | 
			
		||||
	WHO           = "WHO"
 | 
			
		||||
	WHOIS         = "WHOIS"
 | 
			
		||||
	defaultSplit  = 450
 | 
			
		||||
	defaultMarker = "..."
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// cutNewLines() pares down a string to the part before the first "\r" or "\n".
 | 
			
		||||
| 
						 | 
				
			
			@ -65,21 +66,34 @@ func indexFragment(s string) int {
 | 
			
		|||
	return -1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SplitDefaults permits read-only access to goirc's default split params.
 | 
			
		||||
func SplitDefaults() (int, string) {
 | 
			
		||||
	return defaultSplit, defaultMarker
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// splitMessage splits a message > splitLen chars at:
 | 
			
		||||
//   1. the end of the last sentence fragment before splitLen
 | 
			
		||||
//   2. the end of the last word before splitLen
 | 
			
		||||
//   3. splitLen itself
 | 
			
		||||
func splitMessage(msg string, splitLen int) (msgs []string) {
 | 
			
		||||
func splitMessage(msg string, splitLen int, marker string) (msgs []string) {
 | 
			
		||||
	// This is quite short ;-)
 | 
			
		||||
	if splitLen < 13 {
 | 
			
		||||
		splitLen = defaultSplit
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	markerLen := len(marker)
 | 
			
		||||
	if markerLen >= splitLen {
 | 
			
		||||
		// This will end badly otherwise :-)
 | 
			
		||||
		markerLen = len(defaultMarker)
 | 
			
		||||
		marker = defaultMarker
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for len(msg) > splitLen {
 | 
			
		||||
		idx := indexFragment(msg[:splitLen-3])
 | 
			
		||||
		idx := indexFragment(msg[:splitLen-markerLen])
 | 
			
		||||
		if idx < 0 {
 | 
			
		||||
			idx = splitLen - 3
 | 
			
		||||
			idx = splitLen - markerLen
 | 
			
		||||
		}
 | 
			
		||||
		msgs = append(msgs, msg[:idx]+"...")
 | 
			
		||||
		msgs = append(msgs, msg[:idx]+marker)
 | 
			
		||||
		msg = msg[idx:]
 | 
			
		||||
	}
 | 
			
		||||
	return append(msgs, msg)
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +191,7 @@ func (conn *Conn) Who(nick string) { conn.Raw(WHO + " " + nick) }
 | 
			
		|||
// PRIVMSG t :msg
 | 
			
		||||
func (conn *Conn) Privmsg(t, msg string) {
 | 
			
		||||
	prefix := PRIVMSG + " " + t + " :"
 | 
			
		||||
	for _, s := range splitMessage(msg, conn.cfg.SplitLen) {
 | 
			
		||||
	for _, s := range splitMessage(msg, conn.cfg.SplitLen, conn.cfg.SplitMarker) {
 | 
			
		||||
		conn.Raw(prefix + s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -207,7 +221,7 @@ func (conn *Conn) Privmsgf(t, format string, a ...interface{}) {
 | 
			
		|||
// will be sent to the target containing sequential parts of msg.
 | 
			
		||||
//     NOTICE t :msg
 | 
			
		||||
func (conn *Conn) Notice(t, msg string) {
 | 
			
		||||
	for _, s := range splitMessage(msg, conn.cfg.SplitLen) {
 | 
			
		||||
	for _, s := range splitMessage(msg, conn.cfg.SplitLen, conn.cfg.SplitMarker) {
 | 
			
		||||
		conn.Raw(NOTICE + " " + t + " :" + s)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +231,7 @@ func (conn *Conn) Notice(t, msg string) {
 | 
			
		|||
//     PRIVMSG t :\001CTCP arg\001
 | 
			
		||||
func (conn *Conn) Ctcp(t, ctcp string, arg ...string) {
 | 
			
		||||
	// We need to split again here to ensure
 | 
			
		||||
	for _, s := range splitMessage(strings.Join(arg, " "), conn.cfg.SplitLen) {
 | 
			
		||||
	for _, s := range splitMessage(strings.Join(arg, " "), conn.cfg.SplitLen, conn.cfg.SplitMarker) {
 | 
			
		||||
		if s != "" {
 | 
			
		||||
			s = " " + s
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -230,7 +244,7 @@ func (conn *Conn) Ctcp(t, ctcp string, arg ...string) {
 | 
			
		|||
// or channel t, with an optional argument.
 | 
			
		||||
//     NOTICE t :\001CTCP arg\001
 | 
			
		||||
func (conn *Conn) CtcpReply(t, ctcp string, arg ...string) {
 | 
			
		||||
	for _, s := range splitMessage(strings.Join(arg, " "), conn.cfg.SplitLen) {
 | 
			
		||||
	for _, s := range splitMessage(strings.Join(arg, " "), conn.cfg.SplitLen, conn.cfg.SplitMarker) {
 | 
			
		||||
		if s != "" {
 | 
			
		||||
			s = " " + s
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,26 +62,35 @@ func TestSplitMessage(t *testing.T) {
 | 
			
		|||
	tests := []struct {
 | 
			
		||||
		in  string
 | 
			
		||||
		sp  int
 | 
			
		||||
		mk  string
 | 
			
		||||
		out []string
 | 
			
		||||
	}{
 | 
			
		||||
		{"", 0, []string{""}},
 | 
			
		||||
		{"foo", 0, []string{"foo"}},
 | 
			
		||||
		{"foo bar baz beep", 0, []string{"foo bar baz beep"}},
 | 
			
		||||
		{"foo bar baz beep", 15, []string{"foo bar baz ...", "beep"}},
 | 
			
		||||
		{"foo bar, baz beep", 15, []string{"foo bar, ...", "baz beep"}},
 | 
			
		||||
		{"01234567890123456", 0, []string{"01234567890123456"}},
 | 
			
		||||
		{"01234567890123456", 13, []string{"0123456789...", "0123456"}},
 | 
			
		||||
		{"01234567890123456", 14, []string{"01234567890...", "123456"}},
 | 
			
		||||
		{"01234567890123456", 15, []string{"012345678901...", "23456"}},
 | 
			
		||||
		{"01234567890123456", 16, []string{"0123456789012...", "3456"}},
 | 
			
		||||
		{"01234567890123456", 17, []string{"01234567890123456"}},
 | 
			
		||||
		{longString, 0, []string{longString[:longIdx] + "...", longString[longIdx:]}},
 | 
			
		||||
		{longString[:defaultSplit-1], 0, []string{longString[:defaultSplit-1]}},
 | 
			
		||||
		{longString[:defaultSplit], 0, []string{longString[:defaultSplit]}},
 | 
			
		||||
		{longString[:defaultSplit+1], 0, []string{longString[:longIdx] + "...", longString[longIdx : defaultSplit+1]}},
 | 
			
		||||
		{"", 0, "...", []string{""}},
 | 
			
		||||
		{"foo", 0, "...", []string{"foo"}},
 | 
			
		||||
		{"foo bar baz beep", 0, "...", []string{"foo bar baz beep"}},
 | 
			
		||||
		{"foo bar baz beep", 15, "...", []string{"foo bar baz ...", "beep"}},
 | 
			
		||||
		{"foo bar, baz beep", 15, "...", []string{"foo bar, ...", "baz beep"}},
 | 
			
		||||
		{"01234567890123456", 0, "...", []string{"01234567890123456"}},
 | 
			
		||||
		{"01234567890123456", 13, "", []string{"0123456789012", "3456"}},
 | 
			
		||||
		{"01234567890123456", 14, ".", []string{"0123456789012.", "3456"}},
 | 
			
		||||
		{"01234567890123456", 15, "..", []string{"0123456789012..", "3456"}},
 | 
			
		||||
		{"01234567890123456", 16, "...", []string{"0123456789012...", "3456"}},
 | 
			
		||||
		{"01234567890123456", 17, "...", []string{"01234567890123456"}},
 | 
			
		||||
		{"01234567890123456", 14, "abcdefg", []string{"0123456abcdefg", "7890123456"}},
 | 
			
		||||
		{"01234567890123456", 14, "abcdefghijkl", []string{
 | 
			
		||||
			"01abcdefghijkl",
 | 
			
		||||
			"23abcdefghijkl",
 | 
			
		||||
			"4567890123456",
 | 
			
		||||
		}},
 | 
			
		||||
		// splitlen = markerlen => reset to default marker
 | 
			
		||||
		{"01234567890123456", 14, "abcdefghijklmn", []string{"01234567890...", "123456"}},
 | 
			
		||||
		{longString, 0, "...", []string{longString[:longIdx] + "...", longString[longIdx:]}},
 | 
			
		||||
		{longString[:defaultSplit-1], 0, "...", []string{longString[:defaultSplit-1]}},
 | 
			
		||||
		{longString[:defaultSplit], 0, "...", []string{longString[:defaultSplit]}},
 | 
			
		||||
		{longString[:defaultSplit+1], 0, "...", []string{longString[:longIdx] + "...", longString[longIdx : defaultSplit+1]}},
 | 
			
		||||
	}
 | 
			
		||||
	for i, test := range tests {
 | 
			
		||||
		out := splitMessage(test.in, test.sp)
 | 
			
		||||
		out := splitMessage(test.in, test.sp, test.mk)
 | 
			
		||||
		if !reflect.DeepEqual(test.out, out) {
 | 
			
		||||
			t.Errorf("test %d: expected %q, got %q", i, test.out, out)
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -136,6 +136,8 @@ type Config struct {
 | 
			
		|||
	// Split PRIVMSGs, NOTICEs and CTCPs longer than SplitLen characters
 | 
			
		||||
	// over multiple lines. Default to 450 if not set.
 | 
			
		||||
	SplitLen int
 | 
			
		||||
	// Defaults to appending "..." to a split line to indicate a split.
 | 
			
		||||
	SplitMarker string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// NewConfig creates a Config struct containing sensible defaults.
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +151,7 @@ func NewConfig(nick string, args ...string) *Config {
 | 
			
		|||
		NewNick:                     DefaultNewNick,
 | 
			
		||||
		Recover:                     (*Conn).LogPanic, // in dispatch.go
 | 
			
		||||
		SplitLen:                    defaultSplit,
 | 
			
		||||
		SplitMarker:                 defaultMarker,
 | 
			
		||||
		Timeout:                     60 * time.Second,
 | 
			
		||||
		EnableCapabilityNegotiation: false,
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue