about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorReto Brunner <reto@labrat.space>2020-08-26 08:13:38 +0200
committerReto Brunner <reto@labrat.space>2020-08-27 08:38:41 +0200
commit720733bc6e534503bd88d8087ac0446c4c516d4a (patch)
treecb184706549f1ab888b654af600bf409fba9a7c4
parentb6ef116c36e1a1de6a2289f392603fd51a2b91da (diff)
downloadaerc-720733bc6e534503bd88d8087ac0446c4c516d4a.tar.gz
reply: use set instead of linear search
-rw-r--r--commands/msg/reply.go115
1 files changed, 70 insertions, 45 deletions
diff --git a/commands/msg/reply.go b/commands/msg/reply.go
index d4b3be6..3c8016e 100644
--- a/commands/msg/reply.go
+++ b/commands/msg/reply.go
@@ -64,10 +64,11 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
 	if err != nil {
 		return err
 	}
-	alias_of_us, err := format.ParseAddressList(conf.Aliases)
+	aliases, err := format.ParseAddressList(conf.Aliases)
 	if err != nil {
 		return err
 	}
+
 	store := widget.Store()
 	if store == nil {
 		return errors.New("Cannot perform action. Messages still loading")
@@ -77,61 +78,63 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
 		return err
 	}
 
+	// figure out the sending from address if we have aliases
+	if len(aliases) != 0 {
+		rec := newAddrSet()
+		rec.AddList(msg.Envelope.To)
+		rec.AddList(msg.Envelope.Cc)
+		// test the from first, it has priority over any present alias
+		if rec.Contains(from) {
+			// do nothing
+		} else {
+			for _, a := range aliases {
+				if rec.Contains(a) {
+					from = a
+					break
+				}
+			}
+		}
+	}
+
 	var (
 		to []*models.Address
 		cc []*models.Address
 	)
-	if args[0] == "reply" {
-		if len(msg.Envelope.ReplyTo) != 0 {
-			to = msg.Envelope.ReplyTo
-		} else {
-			to = msg.Envelope.From
-		}
 
-		// figure out the sending from address if we have aliases
-		if len(alias_of_us) != 0 {
-			allRecipients := append(msg.Envelope.To, msg.Envelope.Cc...)
-		outer:
-			for _, addr := range allRecipients {
-				if addr.Address == from.Address {
-					from = addr
-					break
-				}
-				for _, alias := range alias_of_us {
-					if addr.Address == alias.Address {
-						from = addr
-						break outer
-					}
-				}
-			}
+	recSet := newAddrSet() // used for de-duping
 
-		}
+	if len(msg.Envelope.ReplyTo) != 0 {
+		to = msg.Envelope.ReplyTo
+	} else {
+		to = msg.Envelope.From
+	}
+	recSet.AddList(to)
 
-		isMainRecipient := func(a *models.Address) bool {
-			for _, ta := range to {
-				if ta.Address == a.Address {
-					return true
-				}
+	if replyAll {
+		// order matters, due to the deduping
+		// in order of importance, first parse the To, then the Cc header
+
+		// we add our from address, so that we don't self address ourselves
+		recSet.Add(from)
+
+		envTos := make([]*models.Address, 0, len(msg.Envelope.To))
+		for _, addr := range msg.Envelope.To {
+			if recSet.Contains(addr) {
+				continue
 			}
-			return false
+			envTos = append(envTos, addr)
 		}
-		if replyAll {
-			for _, addr := range msg.Envelope.Cc {
-				//dedupe stuff from the to/from headers
-				if isMainRecipient(addr) || addr.Address == from.Address {
-					continue
-				}
-				cc = append(cc, addr)
-			}
-			envTos := make([]*models.Address, 0, len(msg.Envelope.To))
-			for _, addr := range msg.Envelope.To {
-				if addr.Address == from.Address {
-					continue
-				}
-				envTos = append(envTos, addr)
+		recSet.AddList(envTos)
+		to = append(to, envTos...)
+
+		for _, addr := range msg.Envelope.Cc {
+			//dedupe stuff from the to/from headers
+			if recSet.Contains(addr) {
+				continue
 			}
-			to = append(to, envTos...)
+			cc = append(cc, addr)
 		}
+		recSet.AddList(cc)
 	}
 
 	var subject string
@@ -218,3 +221,25 @@ func (reply) Execute(aerc *widgets.Aerc, args []string) error {
 		return addTab()
 	}
 }
+
+type addrSet map[string]struct{}
+
+func newAddrSet() addrSet {
+	s := make(map[string]struct{})
+	return addrSet(s)
+}
+
+func (s addrSet) Add(a *models.Address) {
+	s[a.Address] = struct{}{}
+}
+
+func (s addrSet) AddList(al []*models.Address) {
+	for _, a := range al {
+		s[a.Address] = struct{}{}
+	}
+}
+
+func (s addrSet) Contains(a *models.Address) bool {
+	_, ok := s[a.Address]
+	return ok
+}