mirror of
https://github.com/anthropics/claude-code.git
synced 2026-02-19 04:27:33 -08:00
Adds a new plugin that transforms plain Slack forwarded message blocks into visually distinctive formatted boxes using Unicode box-drawing characters. Before: [Forwarded Message] From: Felix Klock Message: Here is some text... After: ╔════════════════════════════════════════════════════════════════════╗ ║ FORWARDED MESSAGE ║ ╠════════════════════════════════════════════════════════════════════╣ ║ From: Felix Klock ║ ╟────────────────────────────────────────────────────────────────────╢ ║ Here is some text... ║ ╚════════════════════════════════════════════════════════════════════╝ The plugin uses a UserPromptSubmit hook to intercept prompts containing [Forwarded Message] blocks and reformats them for better visual distinction. https://claude.ai/code/session_01YNRC6p2gAMSQZPX2NGK5F1
186 lines
6.1 KiB
Python
Executable File
186 lines
6.1 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Slack Quote Formatter - UserPromptSubmit Hook
|
|
|
|
Transforms plain Slack forwarded/quoted messages into visually distinctive
|
|
formatted blocks with Unicode box characters and better layout.
|
|
|
|
Before:
|
|
[Forwarded Message]
|
|
From: John Doe
|
|
Message: Here is some text...
|
|
|
|
After:
|
|
╔═══════════════════════════════════════════════════════════╗
|
|
║ FORWARDED MESSAGE ║
|
|
╠═══════════════════════════════════════════════════════════╣
|
|
║ From: John Doe ║
|
|
╟───────────────────────────────────────────────────────────╢
|
|
║ Here is some text... ║
|
|
╚═══════════════════════════════════════════════════════════╝
|
|
"""
|
|
|
|
import json
|
|
import re
|
|
import sys
|
|
|
|
|
|
def format_forwarded_message(from_line: str, message_content: str) -> str:
|
|
"""Format a single forwarded message with visual box styling."""
|
|
|
|
# Box drawing characters
|
|
TOP_LEFT = "╔"
|
|
TOP_RIGHT = "╗"
|
|
BOTTOM_LEFT = "╚"
|
|
BOTTOM_RIGHT = "╝"
|
|
HORIZONTAL = "═"
|
|
VERTICAL = "║"
|
|
LEFT_T = "╠"
|
|
RIGHT_T = "╣"
|
|
LEFT_LIGHT = "╟"
|
|
RIGHT_LIGHT = "╢"
|
|
LIGHT_HORIZONTAL = "─"
|
|
|
|
# Configuration
|
|
BOX_WIDTH = 70
|
|
INNER_WIDTH = BOX_WIDTH - 4 # Account for "║ " and " ║"
|
|
|
|
def pad_line(text: str, width: int = INNER_WIDTH) -> str:
|
|
"""Pad a line to fill the box width."""
|
|
if len(text) > width:
|
|
return text[:width]
|
|
return text + " " * (width - len(text))
|
|
|
|
def wrap_text(text: str, width: int) -> list:
|
|
"""Wrap text to fit within the specified width."""
|
|
words = text.split()
|
|
lines = []
|
|
current_line = []
|
|
current_length = 0
|
|
|
|
for word in words:
|
|
word_len = len(word)
|
|
if current_length + word_len + (1 if current_line else 0) <= width:
|
|
current_line.append(word)
|
|
current_length += word_len + (1 if len(current_line) > 1 else 0)
|
|
else:
|
|
if current_line:
|
|
lines.append(" ".join(current_line))
|
|
current_line = [word]
|
|
current_length = word_len
|
|
|
|
if current_line:
|
|
lines.append(" ".join(current_line))
|
|
|
|
return lines if lines else [""]
|
|
|
|
lines = []
|
|
|
|
# Top border with header
|
|
lines.append(f"{TOP_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{TOP_RIGHT}")
|
|
|
|
# Header line
|
|
header = "FORWARDED MESSAGE"
|
|
lines.append(f"{VERTICAL} {pad_line(header)}{VERTICAL}")
|
|
|
|
# Separator after header
|
|
lines.append(f"{LEFT_T}{HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_T}")
|
|
|
|
# From line
|
|
from_display = from_line.strip()
|
|
lines.append(f"{VERTICAL} {pad_line(from_display)}{VERTICAL}")
|
|
|
|
# Light separator before message
|
|
lines.append(f"{LEFT_LIGHT}{LIGHT_HORIZONTAL * (BOX_WIDTH - 2)}{RIGHT_LIGHT}")
|
|
|
|
# Message content (indented and wrapped)
|
|
message_lines = message_content.strip().split("\n")
|
|
for msg_line in message_lines:
|
|
# Handle each line, wrapping if necessary
|
|
wrapped = wrap_text(msg_line, INNER_WIDTH - 2) # Extra indent
|
|
for wrapped_line in wrapped:
|
|
indented = " " + wrapped_line # Add indent for quote appearance
|
|
lines.append(f"{VERTICAL} {pad_line(indented)}{VERTICAL}")
|
|
|
|
# Bottom border
|
|
lines.append(f"{BOTTOM_LEFT}{HORIZONTAL * (BOX_WIDTH - 2)}{BOTTOM_RIGHT}")
|
|
|
|
return "\n".join(lines)
|
|
|
|
|
|
def transform_slack_context(text: str) -> str:
|
|
"""
|
|
Find and transform [Forwarded Message] blocks in the text.
|
|
|
|
Matches patterns like:
|
|
[Forwarded Message]
|
|
From: Name Here
|
|
Message: Content here that may span
|
|
multiple lines until we hit the next section
|
|
"""
|
|
|
|
# Pattern to match forwarded message blocks
|
|
# This handles the common format from Slack context
|
|
pattern = r'\[Forwarded Message\]\s*\n\s*From:\s*([^\n]+)\s*\nMessage:\s*(.+?)(?=\n\s*\[|\n\[pnkfelix\]|\n<|\Z)'
|
|
|
|
def replace_match(match):
|
|
from_name = match.group(1).strip()
|
|
message = match.group(2).strip()
|
|
|
|
formatted = format_forwarded_message(f"From: {from_name}", message)
|
|
return f"\n{formatted}\n"
|
|
|
|
# Apply transformation
|
|
result = re.sub(pattern, replace_match, text, flags=re.DOTALL)
|
|
|
|
return result
|
|
|
|
|
|
def main():
|
|
"""Main entry point for the UserPromptSubmit hook."""
|
|
try:
|
|
# Read input from stdin
|
|
input_data = json.load(sys.stdin)
|
|
|
|
# Get the user prompt if available
|
|
user_prompt = input_data.get("user_prompt", "")
|
|
|
|
if not user_prompt:
|
|
# No prompt to transform, just pass through
|
|
print(json.dumps({}))
|
|
sys.exit(0)
|
|
|
|
# Check if there are forwarded messages to format
|
|
if "[Forwarded Message]" not in user_prompt:
|
|
# Nothing to transform
|
|
print(json.dumps({}))
|
|
sys.exit(0)
|
|
|
|
# Transform the prompt
|
|
transformed_prompt = transform_slack_context(user_prompt)
|
|
|
|
# If we made changes, return the transformed prompt
|
|
if transformed_prompt != user_prompt:
|
|
result = {
|
|
"transformedPrompt": transformed_prompt
|
|
}
|
|
print(json.dumps(result))
|
|
else:
|
|
print(json.dumps({}))
|
|
|
|
except json.JSONDecodeError:
|
|
# No valid JSON input, pass through
|
|
print(json.dumps({}))
|
|
except Exception as e:
|
|
# Log error but don't block
|
|
error_output = {
|
|
"systemMessage": f"[slack-quote-formatter] Warning: {str(e)}"
|
|
}
|
|
print(json.dumps(error_output))
|
|
|
|
sys.exit(0)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|