Jump to content

Recommended Posts

I'm building a workflow that will accept a string input and output the same string with some characters escaped using '\'. This is so the string can be accepted into a function which accepts regular expressions.

 

I have a python script that does this perfectly and Alfred will do it perfectly as well up to about 60-70 characters. After that it just defaults to the "Search Google for {my string}".

 

My question is a) is there a character limit on arguments passed into Alfred and B) is there a way to bypass it?

 

Thank you!

Link to comment

It does work fine on the command line. I have to wrap my string in quotes to get it to work but the one I'm testing (and works on the command line) is 1192 characters. 

 

I wonder if it's an issue with encoding? I'm going from utf-8 to ascii within the script.

 

Might it also be an issue with copying into the alfred argument field? The workflow right now is type 'reg', and copy my string in. I don't type it in. 

Link to comment

Sorry, I replied before I saw your reply.

 

Here's the script I'm running. When I run a string like 'This-is a string with some stuff-in it' it correctly outputs: This\-is a string with some stuff\-in it. 

 

But if I run the string 'But now my string|has pipes and 'quotes' nothing happens. it does work on the command line and correctly outputs the xml <items><item arg="But not my string|has pipes and \'quotes" uid="regexified" valid="yes"><title>But now my string|has pipes and \'quotes</title><subtitle>Copy to Clipboard</subtitle><icon /></item></items>

 

I want to keep pipes in there and un-escaped. 

 

And no, I don't see any errors on the console.

# -*- coding: utf-8 -*-
import sys
from xml.etree.ElementTree import Element, SubElement, Comment,  tostring

args = sys.argv

string_to_regex = str(args[1]).decode('utf-8')

regexified = []

# Builds each part of the XML tree
def build_xmltree(items):
	item = SubElement(items, 'item')
	title = SubElement(item, 'title')
	subtitle = SubElement(item, 'subtitle')
	icon = SubElement(item, 'icon')
	return (item, title, subtitle, icon)

for i in string_to_regex:
	if i in ["-","\\","(",")",",","'",">","<"]:
		regexified.append("\\"+ i)
	else:
		regexified.append(i)

alfred = ''.join(regexified)
alfred_two = alfred.encode('ascii', 'ignore')

items = Element('items')

item, title, subtitle, icon = build_xmltree(items)

item.set('uid', 'regexified')
item.set('arg', alfred_two)
item.set('valid', 'yes')
 
title.text = alfred 
subtitle.text = 'Copy to Clipboard'

print tostring(items)
Edited by Veritas3241
Link to comment

 

Sorry, I replied before I saw your reply.

 

Here's the script I'm running. When I run a string like 'This-is a string with some stuff-in it' it correctly outputs: This\-is a string with some stuff\-in it. 

 

But if I run the string 'But now my string|has pipes and 'quotes' nothing happens. it does work on the command line and correctly outputs the xml <items><item arg="But not my string|has pipes and \'quotes" uid="regexified" valid="yes"><title>But now my string|has pipes and \'quotes</title><subtitle>Copy to Clipboard</subtitle><icon /></item></items>

 

I want to keep pipes in there and un-escaped. 

 

And no, I don't see any errors on the console.

# -*- coding: utf-8 -*-
import sys
from xml.etree.ElementTree import Element, SubElement, Comment,  tostring

args = sys.argv

string_to_regex = str(args[1]).decode('utf-8')

regexified = []

# Builds each part of the XML tree
def build_xmltree(items):
	item = SubElement(items, 'item')
	title = SubElement(item, 'title')
	subtitle = SubElement(item, 'subtitle')
	icon = SubElement(item, 'icon')
	return (item, title, subtitle, icon)

for i in string_to_regex:
	if i in ["-","\\","(",")",",","'",">","<"]:
		regexified.append("\\"+ i)
	else:
		regexified.append(i)

alfred = ''.join(regexified)
alfred_two = alfred.encode('ascii', 'ignore')

items = Element('items')

item, title, subtitle, icon = build_xmltree(items)

item.set('uid', 'regexified')
item.set('arg', alfred_two)
item.set('valid', 'yes')
 
title.text = alfred 
subtitle.text = 'Copy to Clipboard'

print tostring(items)

 

I replaced your \' with ' and everything works. Your XML was invalid because of the improperly escaped apostrophes.

 

I recommend using a workflow library in your code. It will abstract all this escaping business and make it easier to interact with Alfred :)

Link to comment

The output escaping isn't the problem—he's letting the XML library do that, as would any Alfred library.

 

The big problem is the text encoding is all over the place. Veritas, you're mixing unicode strings (string_to_regex) and UTF-8-encoded strings (everything else). You must encode the output to UTF-8 before printing it to Alfred.

 

Try this instead:

# -*- coding: utf-8 -*-
import sys
from xml.etree.ElementTree import Element, SubElement, Comment,  tostring

string_to_regex = sys.argv[1].decode(u'utf-8')

regexified = []

# Builds each part of the XML tree
def build_xmltree(items):
	item = SubElement(items, u'item')
	title = SubElement(item, u'title')
	subtitle = SubElement(item, u'subtitle')
	icon = SubElement(item, u'icon')
	return (item, title, subtitle, icon)

for i in string_to_regex:
	if i in u"\\[]().*+-^$|":
		regexified.append(u"\\" + i)
	else:
		regexified.append(i)

alfred = u''.join(regexified)

items = Element(u'items')

item, title, subtitle, icon = build_xmltree(items)

item.set(u'uid', u'regexified')
item.set(u'arg', alfred)
item.set(u'valid', u'yes')
 
title.text = alfred 
subtitle.text = u'Copy to Clipboard'

print tostring(items, encoding=u'utf-8')

And set up the script escaping so:

 

oy1j4kO.png

 

It should do what you want (if I've understood it correctly).

 

A lot of the strings I've changed to unicode literals are unnecessary (tag names, 'utf-8' etc.), but it's a good habit to get into with Python 2, otherwise at some point you'll combine unicode and non-unicode and bad things will happen.

 

Be sure to decode all external input (sys.argv, os.environ, sys.stdin etc.) to unicode immediately, and encode all output (usually to UTF-8) before you print/write it.

 

If you don't do that, any non-ASCII character will likely break your script.

 

If you're working with filepaths, you also have to call unicodedata.normalize(u'NFD', u'your unicode path here') or weird things will happen (on OS X).

Edited by deanishe
Link to comment

This script worked exactly like I need it to. I'm a complete noob at dealing with all of the encoding issues. I'm still trying to wrap my head around it all. 

 

For now, I'm going to use the script like you wrote it, but I still might try my hand incorporating one of the libraries.

 

Thank you very much for your help!

Link to comment

You're welcome.

 

Here's the Python Unicode tutorial, but the golden rule is decode on input, encode on output. You should always test your scripts with non-ASCII input to flush out any errors.

 

Most of the Alfred libraries are overkill for a simple script like this one, but you might give nikipore's one a try. It's nice and lightweight (just one file), and does a good job with encoding. Alp, by contrast, is very bloated (and therefore slow) and does not do encoding correctly (wrong normalisation for OS X).

Link to comment

In Alp's defense, if I remember correctly, you can just include whatever you need to include and delete the rest.

 

Yes, I can confirm this. I remove unnecessary modules for nearly every Python workflow I write. Each time, a different set is removed according to the workflow's needs.

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...