Copy and paste RTF formatting?

Wanted to add my solution to this since this is first google result. I am a windows user.
I like to use RTF formatting to color code text.
Pasting from clipboard won’t work to preserve rtf formatting, however pasting from wordpad does.

Therefore it possible to make a python script which wraps plain text with RTF formatting. (based on whatever conditions you need)

Then the formatted text can be opened in word pad, and you can paste back into scrivener.

So the workflow is β†’ write text in scrivener β†’ copy the text β†’ run the script β†’ copy new formatted text in wordpad β†’ paste back into scrivener

Example script. This checks for keywords and then highlights lines following the keyword (this is my own custom screenplay format). :

import os
import subprocess
import tkinter as tk

# Define a dictionary with keywords and their corresponding RTF formatting
# Example formatting for common keywords like CHARACTER, DIALOG, ACTION, etc.
formatting_map = {
    'CHARACTER': r'\cf1\chcbpat4',  # Black text with blue background for characters
    'NARRATOR': r'\cf2\chcbpat5',   # Light gray text with orange background for narrators
    'ACTION': r'\cf3\chcbpat6',     # Cyan text with green background for actions
    'DIALOG': r'\cf4',              # Yellow text for dialog lines
    'TITLE': r'\cf5\b',             # Bold and different color for titles
}

# Function to get text from clipboard
def get_text_from_clipboard():
    root = tk.Tk()
    root.withdraw()  # Hide the root window
    return root.clipboard_get()

# Convert the clipboard text to an RTF formatted string
def convert_to_rtf(text_lines, formatting_map):
    # Sample RTF header with a color table for generic use cases
    rtf_header = r'{\rtf1\ansi\ansicpg1252\uc1\deff0{\fonttbl{\f0\fmodern\fcharset0\fprq2 Cascadia Mono;}}' \
                 r'{\colortbl;\red0\green0\blue0;\red255\green255\blue255;' \
                 r'\red128\green128\blue128;\red72\green207\blue254;\red252\green226\blue33;' \
                 r'\red0\green255\blue255;\red0\green255\blue127;\red253\green146\blue101;}\n'
    rtf_footer = r'\par}'

    rtf_content = ""
    current_format = ""

    for line in text_lines.splitlines():
        if line.strip() == "":
            rtf_content += r'\pard\plain \par\n'  # Preserve blank lines
            continue

        # Check if the line starts with a keyword
        formatted = False
        for keyword, rtf_format in formatting_map.items():
            if line.strip().startswith(keyword):
                current_format = rtf_format  # Set the current formatting to this keyword
                rtf_content += r'\pard\plain \tx360\ql\ltrch\loch \f0\fs24\b0\i0 ' + current_format + ' ' + line.strip() + r' \par\n'
                formatted = True
                break

        # If the line doesn't start with a keyword, continue with the current formatting
        if not formatted and current_format:
            rtf_content += r'\pard\plain \tx360\ql\ltrch\loch \f0\fs24\b0\i0 ' + current_format + ' ' + line.strip() + r' \par\n'

    return rtf_header + rtf_content + rtf_footer

# Save the RTF formatted text to a file
def save_rtf_file(rtf_content, output_file):
    with open(output_file, 'w') as file:
        file.write(rtf_content)

# Open the RTF file in WordPad
def open_in_wordpad(file_path):
    subprocess.run(['write', file_path])

# Main script
if __name__ == "__main__":
    # Get text from clipboard
    clipboard_text = get_text_from_clipboard()

    if clipboard_text:
        # Define the output file path
        output_file = 'output.rtf'

        # Convert the clipboard text to RTF
        rtf_content = convert_to_rtf(clipboard_text, formatting_map)

        # Save the RTF file
        save_rtf_file(rtf_content, output_file)

        # Open the file in WordPad
        open_in_wordpad(output_file)
    else:
        print("No text found in clipboard.")

1 Like