chore: add more plugin examples (#395)

Drew Smirnoff and Lea created

Co-authored-by: Lea <lea@floatpane.com>

Change summary

examples/plugins/account_indicator.lua   |  8 +++++++
examples/plugins/attachment_reminder.lua | 25 +++++++++++++++++++++++
examples/plugins/domain_filter.lua       | 19 +++++++++++++++++
examples/plugins/email_age.lua           | 12 +++++++++++
examples/plugins/empty_body_guard.lua    | 10 +++++++++
examples/plugins/folder_favorites.lua    | 27 +++++++++++++++++++++++++
examples/plugins/greeting.lua            | 18 ++++++++++++++++
examples/plugins/inbox_activity.lua      | 26 ++++++++++++++++++++++++
examples/plugins/keyword_highlighter.lua | 24 ++++++++++++++++++++++
examples/plugins/read_tracker.lua        | 11 ++++++++++
examples/plugins/reading_time.lua        | 20 ++++++++++++++++++
examples/plugins/recipient_counter.lua   | 17 +++++++++++++++
examples/plugins/reply_all_warn.lua      | 19 +++++++++++++++++
examples/plugins/self_email_warn.lua     | 13 ++++++++++++
examples/plugins/sender_frequency.lua    | 28 ++++++++++++++++++++++++++
examples/plugins/session_stats.lua       | 25 +++++++++++++++++++++++
examples/plugins/spam_detector.lua       | 25 +++++++++++++++++++++++
examples/plugins/subject_length_warn.lua | 14 +++++++++++++
examples/plugins/subject_reminder.lua    | 10 +++++++++
examples/plugins/thread_tracker.lua      | 17 +++++++++++++++
examples/plugins/vip_alerts.lua          | 20 ++++++++++++++++++
examples/plugins/word_counter.lua        | 12 +++++++++++
22 files changed, 400 insertions(+)

Detailed changes

examples/plugins/account_indicator.lua 🔗

@@ -0,0 +1,8 @@
+-- account_indicator.lua
+-- Shows which account received the email you're currently viewing.
+
+local matcha = require("matcha")
+
+matcha.on("email_viewed", function(email)
+    matcha.set_status("email_view", "Account: " .. email.account_id)
+end)

examples/plugins/attachment_reminder.lua 🔗

@@ -0,0 +1,25 @@
+-- attachment_reminder.lua
+-- Warns if your email body mentions an attachment but you might have
+-- forgotten to attach it. Checks common phrases before sending.
+
+local matcha = require("matcha")
+
+local phrases = {
+    "attach",
+    "attached",
+    "attachment",
+    "enclosed",
+    "find attached",
+    "see attached",
+    "i've attached",
+}
+
+matcha.on("composer_updated", function(state)
+    local body = state.body:lower()
+    for _, phrase in ipairs(phrases) do
+        if body:find(phrase, 1, true) then
+            matcha.set_status("composer", "Don't forget the attachment!")
+            return
+        end
+    end
+end)

examples/plugins/domain_filter.lua 🔗

@@ -0,0 +1,19 @@
+-- domain_filter.lua
+-- Highlights emails from specific domains with a notification.
+-- Useful for filtering work vs. personal emails.
+
+local matcha = require("matcha")
+
+local watched_domains = {
+    "company.com",
+    "work.org",
+}
+
+matcha.on("email_received", function(email)
+    for _, domain in ipairs(watched_domains) do
+        if email.from:match("@" .. domain:gsub("%.", "%%.") .. "$") then
+            matcha.notify("Work email: " .. email.subject, 2)
+            return
+        end
+    end
+end)

examples/plugins/email_age.lua 🔗

@@ -0,0 +1,12 @@
+-- email_age.lua
+-- Shows the date of the email you're viewing in the status bar.
+
+local matcha = require("matcha")
+
+matcha.on("email_viewed", function(email)
+    -- Show the date portion of the RFC3339 timestamp.
+    local date = email.date:match("^(%d%d%d%d%-%d%d%-%d%d)")
+    if date then
+        matcha.set_status("email_view", "Date: " .. date)
+    end
+end)

examples/plugins/empty_body_guard.lua 🔗

@@ -0,0 +1,10 @@
+-- empty_body_guard.lua
+-- Warns before sending an email with an empty body.
+
+local matcha = require("matcha")
+
+matcha.on("composer_updated", function(state)
+    if state.body_len == 0 and state.to ~= "" then
+        matcha.set_status("composer", "Email body is empty")
+    end
+end)

examples/plugins/folder_favorites.lua 🔗

@@ -0,0 +1,27 @@
+-- folder_favorites.lua
+-- Tracks your most visited folders and logs the top 3 on shutdown.
+
+local matcha = require("matcha")
+
+local visits = {}
+
+matcha.on("folder_changed", function(folder)
+    visits[folder] = (visits[folder] or 0) + 1
+end)
+
+matcha.on("shutdown", function()
+    -- Sort folders by visit count.
+    local sorted = {}
+    for folder, count in pairs(visits) do
+        table.insert(sorted, { name = folder, count = count })
+    end
+    table.sort(sorted, function(a, b) return a.count > b.count end)
+
+    local top = {}
+    for i = 1, math.min(3, #sorted) do
+        table.insert(top, sorted[i].name .. "(" .. sorted[i].count .. ")")
+    end
+    if #top > 0 then
+        matcha.log("Top folders: " .. table.concat(top, ", "))
+    end
+end)

examples/plugins/greeting.lua 🔗

@@ -0,0 +1,18 @@
+-- greeting.lua
+-- Shows a random motivational greeting on startup.
+
+local matcha = require("matcha")
+
+local greetings = {
+    "Ready to tackle your inbox!",
+    "Let's get through those emails.",
+    "Inbox zero awaits!",
+    "You've got mail... probably.",
+    "Time to reply to that email from last week.",
+    "Email: the original social network.",
+}
+
+matcha.on("startup", function()
+    local pick = greetings[math.random(#greetings)]
+    matcha.notify(pick, 3)
+end)

examples/plugins/inbox_activity.lua 🔗

@@ -0,0 +1,26 @@
+-- inbox_activity.lua
+-- Shows a live activity indicator in the inbox status bar.
+-- Combines received, read, and sent counts into a compact display.
+
+local matcha = require("matcha")
+
+local received = 0
+local sent = 0
+
+local function update_status()
+    matcha.set_status("inbox", "↓" .. received .. " ↑" .. sent)
+end
+
+matcha.on("email_received", function(email)
+    received = received + 1
+    update_status()
+end)
+
+matcha.on("email_send_after", function()
+    sent = sent + 1
+    update_status()
+end)
+
+matcha.on("startup", function()
+    update_status()
+end)

examples/plugins/keyword_highlighter.lua 🔗

@@ -0,0 +1,24 @@
+-- keyword_highlighter.lua
+-- Notifies you when incoming emails contain specific keywords.
+-- Useful for tracking topics across your inbox.
+
+local matcha = require("matcha")
+
+local keywords = {
+    "urgent",
+    "deadline",
+    "invoice",
+    "payment",
+    "meeting",
+    "review",
+}
+
+matcha.on("email_received", function(email)
+    local subj = email.subject:lower()
+    for _, keyword in ipairs(keywords) do
+        if subj:find(keyword, 1, true) then
+            matcha.notify("[" .. keyword .. "] " .. email.subject, 3)
+            return
+        end
+    end
+end)

examples/plugins/read_tracker.lua 🔗

@@ -0,0 +1,11 @@
+-- read_tracker.lua
+-- Displays a running count of emails you've read this session.
+
+local matcha = require("matcha")
+
+local read_count = 0
+
+matcha.on("email_viewed", function(email)
+    read_count = read_count + 1
+    matcha.set_status("email_view", read_count .. " read this session")
+end)

examples/plugins/reading_time.lua 🔗

@@ -0,0 +1,20 @@
+-- reading_time.lua
+-- Estimates reading time based on word count while composing.
+-- Assumes ~200 words per minute average reading speed.
+
+local matcha = require("matcha")
+
+matcha.on("composer_updated", function(state)
+    local words = 0
+    for _ in state.body:gmatch("%S+") do
+        words = words + 1
+    end
+    if words > 0 then
+        local minutes = math.ceil(words / 200)
+        if minutes <= 1 then
+            matcha.set_status("composer", "~1 min read")
+        else
+            matcha.set_status("composer", "~" .. minutes .. " min read")
+        end
+    end
+end)

examples/plugins/recipient_counter.lua 🔗

@@ -0,0 +1,17 @@
+-- recipient_counter.lua
+-- Shows the number of recipients in the composer status bar.
+
+local matcha = require("matcha")
+
+matcha.on("composer_updated", function(state)
+    if state.to == "" then
+        return
+    end
+    local count = 0
+    for _ in state.to:gmatch("[^,]+") do
+        count = count + 1
+    end
+    if count > 1 then
+        matcha.set_status("composer", count .. " recipients")
+    end
+end)

examples/plugins/reply_all_warn.lua 🔗

@@ -0,0 +1,19 @@
+-- reply_all_warn.lua
+-- Warns when sending to many recipients (possible accidental reply-all).
+
+local matcha = require("matcha")
+
+local threshold = 5
+
+matcha.on("email_send_before", function(email)
+    local count = 0
+    for _ in email.to:gmatch("[^,]+") do
+        count = count + 1
+    end
+    for _ in email.cc:gmatch("[^,]+") do
+        count = count + 1
+    end
+    if count >= threshold then
+        matcha.notify("Heads up: sending to " .. count .. " recipients", 3)
+    end
+end)

examples/plugins/self_email_warn.lua 🔗

@@ -0,0 +1,13 @@
+-- self_email_warn.lua
+-- Notifies you when you receive an email you sent to yourself.
+
+local matcha = require("matcha")
+
+matcha.on("email_received", function(email)
+    for i = 1, #email.to do
+        if email.to[i] == email.from then
+            matcha.notify("Self-email: " .. email.subject, 2)
+            return
+        end
+    end
+end)

examples/plugins/sender_frequency.lua 🔗

@@ -0,0 +1,28 @@
+-- sender_frequency.lua
+-- Tracks how many emails each sender sends you and shows repeat senders.
+
+local matcha = require("matcha")
+
+local senders = {}
+
+matcha.on("email_received", function(email)
+    local from = email.from
+    senders[from] = (senders[from] or 0) + 1
+    if senders[from] == 3 then
+        matcha.notify("Frequent sender: " .. from .. " (3+ emails)", 2)
+    end
+end)
+
+matcha.on("shutdown", function()
+    local sorted = {}
+    for sender, count in pairs(senders) do
+        if count > 1 then
+            table.insert(sorted, { addr = sender, count = count })
+        end
+    end
+    table.sort(sorted, function(a, b) return a.count > b.count end)
+
+    for i = 1, math.min(5, #sorted) do
+        matcha.log("Top sender: " .. sorted[i].addr .. " (" .. sorted[i].count .. " emails)")
+    end
+end)

examples/plugins/session_stats.lua 🔗

@@ -0,0 +1,25 @@
+-- session_stats.lua
+-- Tracks emails received, read, and sent during your session.
+
+local matcha = require("matcha")
+
+local stats = { received = 0, read = 0, sent = 0 }
+
+matcha.on("email_received", function(email)
+    stats.received = stats.received + 1
+end)
+
+matcha.on("email_viewed", function(email)
+    stats.read = stats.read + 1
+end)
+
+matcha.on("email_send_after", function()
+    stats.sent = stats.sent + 1
+end)
+
+matcha.on("shutdown", function()
+    matcha.log("Session stats: "
+        .. stats.received .. " received, "
+        .. stats.read .. " read, "
+        .. stats.sent .. " sent")
+end)

examples/plugins/spam_detector.lua 🔗

@@ -0,0 +1,25 @@
+-- spam_detector.lua
+-- Flags incoming emails that match common spam patterns.
+
+local matcha = require("matcha")
+
+local spam_patterns = {
+    "you have won",
+    "claim your prize",
+    "act now",
+    "limited time offer",
+    "click here immediately",
+    "congratulations!",
+    "urgent action required",
+    "unsubscribe",
+}
+
+matcha.on("email_received", function(email)
+    local subj = email.subject:lower()
+    for _, pattern in ipairs(spam_patterns) do
+        if subj:find(pattern, 1, true) then
+            matcha.notify("Possible spam: " .. email.subject, 3)
+            return
+        end
+    end
+end)

examples/plugins/subject_length_warn.lua 🔗

@@ -0,0 +1,14 @@
+-- subject_length_warn.lua
+-- Warns when your subject line is getting too long.
+-- Most email clients truncate subjects beyond ~60 characters.
+
+local matcha = require("matcha")
+
+matcha.on("composer_updated", function(state)
+    local len = #state.subject
+    if len > 78 then
+        matcha.set_status("composer", "Subject too long (" .. len .. " chars)")
+    elseif len > 60 then
+        matcha.set_status("composer", "Subject may truncate (" .. len .. " chars)")
+    end
+end)

examples/plugins/subject_reminder.lua 🔗

@@ -0,0 +1,10 @@
+-- subject_reminder.lua
+-- Warns you if you're composing an email without a subject line.
+
+local matcha = require("matcha")
+
+matcha.on("email_send_before", function(email)
+    if email.subject == "" then
+        matcha.notify("Warning: no subject line!", 3)
+    end
+end)

examples/plugins/thread_tracker.lua 🔗

@@ -0,0 +1,17 @@
+-- thread_tracker.lua
+-- Tracks how many replies and forwards you receive per session.
+
+local matcha = require("matcha")
+
+local replies = 0
+local forwards = 0
+
+matcha.on("email_received", function(email)
+    local subj = email.subject:lower()
+    if subj:match("^re:") or subj:match("^re%[%d+%]:") then
+        replies = replies + 1
+    elseif subj:match("^fwd:") or subj:match("^fw:") then
+        forwards = forwards + 1
+    end
+    matcha.set_status("inbox", replies .. " replies, " .. forwards .. " fwd")
+end)

examples/plugins/vip_alerts.lua 🔗

@@ -0,0 +1,20 @@
+-- vip_alerts.lua
+-- Shows prominent notifications for emails from important senders.
+-- Add your VIP addresses to the list below.
+
+local matcha = require("matcha")
+
+local vips = {
+    "boss@example.com",
+    "ceo@example.com",
+    "partner@example.com",
+}
+
+matcha.on("email_received", function(email)
+    for _, vip in ipairs(vips) do
+        if email.from:find(vip, 1, true) then
+            matcha.notify("VIP: " .. email.from .. " - " .. email.subject, 5)
+            return
+        end
+    end
+end)

examples/plugins/word_counter.lua 🔗

@@ -0,0 +1,12 @@
+-- word_counter.lua
+-- Shows a live word count in the composer help bar.
+
+local matcha = require("matcha")
+
+matcha.on("composer_updated", function(state)
+    local words = 0
+    for _ in state.body:gmatch("%S+") do
+        words = words + 1
+    end
+    matcha.set_status("composer", words .. " words")
+end)