Jump to content

How to make python clipboard workflow work line by line


Recommended Posts

I've created a small workflow that copies selected text—an email address—and when triggered by a hotkey, it either ignores the email if valid, or appends, following a tab space "Invalid email address". What I really wanted to do was instead of taking in one line of text as input, and outputting that text plus the appended text, I would have preferred it work on multiple lines, such that if I were to select a column of email addresses, it would validate them all. I couldn't figure out how to make it work on multiple lines. I'm perfectly open to the idea of validating in some other way, but currently I'm using "Selection in macOS" with a hotkey trigger, which runs the python script, the output of which passes as {query} to "Copy to Clipboard" with Automatically paste to frontmost app selected. Any ideas are welcome.

 

import sys
import re

def validate_email(email):
    pattern = re.compile(r'(?:[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\0c\0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\0c\0e-\x7f])+)\])')
    return pattern.match(email) is not None

query = "{query}"
emails = query.split('\n') # split query into a list of strings
valid_emails = []
invalid_emails = []
for email in emails:
    if validate_email(email.strip()): # validate each email address
        valid_emails.append(email.strip())
    else:
        invalid_emails.append(email.strip()) # add invalid email addresses to a separate list

# write invalid email addresses to stdout with tab space and "Invalid email address" message
for email in invalid_emails:
    query = sys.stdout.write(email + "\t" + "Invalid email address\n")

# write valid email addresses to stdout with newline separator
for email in valid_emails:
    query = sys.stdout.write(email + "\n")

 

Link to comment

Welcome @Jayson,

 

Always prefer with input as argv over with input as {query}. By using {query} you’re passing a multiline string in a way Python doesn’t like. Use the debugger and you’ll see it.


The second problem is that you’re overwriting query and doing nothing to it. Output the value directly.

 

import sys
import re

def validate_email(email):
    pattern = re.compile(r'(?:[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\0c\0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\0c\0e-\x7f])+)\])')
    return pattern.match(email) is not None

emails = sys.argv[1].split('\n') # split query into a list of strings
valid_emails = []
invalid_emails = []
for email in emails:
    if validate_email(email.strip()): # validate each email address
        valid_emails.append(email.strip())
    else:
        invalid_emails.append(email.strip()) # add invalid email addresses to a separate list

# write invalid email addresses to stdout with tab space and "Invalid email address" message
for email in invalid_emails:
    sys.stdout.write(email + "\t" + "Invalid email address\n")

# write valid email addresses to stdout with newline separator
for email in valid_emails:
    sys.stdout.write(email + "\n")

 

Link to comment

Thank you @vitor, that helped me. I went with the following to maintain the order of which I was copying and pasting.

 

import sys
import re

def validate_email(email):
    pattern = re.compile(r'(?:[a-z0-9!#$%&\'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&\'*+/=?^_`{|}~-]+)*|\"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\0c\0e-\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\0c\0e-\x7f])+)\])', re.IGNORECASE)
    return pattern.match(email) is not None

emails = sys.argv[1].split('\n')

# validate each non-blank email address and write to stdout in the order they appear in the input
for email in emails:
    email = email.strip()
    if email:
        if validate_email(email):
            sys.stdout.write(email + "\n")
        else:
            sys.stdout.write(email + "\t" + "Invalid email address\n")
    else:
        sys.stdout.write("\n")

 

Edited by Jayson
Added `re.IGNORECASE` to regex to eliminate emails with uppercase getting invalidated.
Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...