luckman212 Posted September 22, 2019 Share Posted September 22, 2019 (edited) Guys, can anyone help me out? I'm trying to use a `JSON Config` object to set some variables in my workflow. But it's not working. I've read https://www.alfredapp.com/help/workflows/utilities/json/ and done as much googl'ing as I can. I made a simple test workflow that illustrates my dilemma. When setting args using `Args and Vars` (hold SHIFT) it works, but the JSON Config seemingly does nothing. Download below: JSONConfig.alfredworkflow (github) Any ideas? Edited September 22, 2019 by luckman212 Link to comment
deanishe Posted September 22, 2019 Share Posted September 22, 2019 (edited) 2 hours ago, luckman212 said: I've read https://www.alfredapp.com/help/workflows/utilities/json/ and done as much googl'ing as I can. You need to read more carefully This is the example from that page: { "alfredworkflow" : { "arg" : "{query}", "config" : { }, "variables" : { } } } Notice that variables is a sibling of config, not a child. Also, there is no argument field. The config object contains settings for the following workflow element. It is a separate thing. This is your JSON: { "alfredworkflow" : { "config" : { "argument" : "", "variables" : { "a" : "apple", "b" : "ball", "c" : "chips" } } } } This is the correct JSON: { "alfredworkflow" : { "arg" : "{query}", "config" : { }, "variables" : { "a" : "apple", "b" : "ball", "c" : "chips" } } } Edited September 22, 2019 by deanishe Link to comment
luckman212 Posted September 22, 2019 Author Share Posted September 22, 2019 Wow, thanks @deanishe 🤘 Ok so here's where I got tripped up— I right clicked on the configured "Args and Vars" object and selected "Copy Configuration" Then I pasted that into the JSON Config object, and it gives me this: { "alfredworkflow" : { "config" : { "argument" : "", "variables" : { "c" : "chips", "a" : "apple", "b" : "ball" } } } } As you noted, this seems to be incorrect/nonfunctional. So, not sure if this is intended behavior, or a bug... Link to comment
deanishe Posted September 22, 2019 Share Posted September 22, 2019 3 minutes ago, luckman212 said: I right clicked on the configured "Args and Vars" object and selected "Copy Configuration" Ah, right. Well, the Arg and Vars object does have variables in its configuration. The config object is element-specific, though. What works with Arg and Vars won't work with other elements. But I can see how that would lead to confusion. luckman212 1 Link to comment
luckman212 Posted September 22, 2019 Author Share Posted September 22, 2019 5 minutes ago, deanishe said: I can see how that would lead to confusion. Yep. That's what got me. A couple of example workflows featuring the JSON Object would have gone a long way. Thanks again for your help!! Link to comment
deanishe Posted September 22, 2019 Share Posted September 22, 2019 Just now, luckman212 said: A couple of example workflows featuring the JSON Object would have gone a long way. The docs in general would benefit from a bit more depth. It's also just dumb bad luck that you copied the config from an Arg and Vars element. Anything else, and you'd have had the "right" JSON. But you picked the only one (AFAIK) that doesn't have the standard arg and variables fields. Link to comment
luckman212 Posted September 23, 2019 Author Share Posted September 23, 2019 @deanishe sorry to ask, but could you possibly nudge me in the right direction on this? I'm trying to dynamically generate the JSON to set variables using a Script Action (ruby). Got this: require 'json' json = [] cc = 20 for i in 0..cc do varname = 'clip' + (i).to_s clipname = '{clipboard:' + (i).to_s + '}' json.push( varname => clipname ) end puts({ "alfredworkflow" => { "arg" => "{query}", "variables" => json }}.to_json) Which generates almost the right output, but not quite (the variables are output as independent items in []'s instead of as direct descendants of `variables`. Any idea what I'm doing wrong here? Link to comment
deanishe Posted September 23, 2019 Share Posted September 23, 2019 8 minutes ago, luckman212 said: Any idea what I'm doing wrong here? I don't know Ruby, so I'm just guessing, but it looks like you're setting variables to an array, not to a hash. This line json = [] should be json = {}, and json.push( varname => clipname ) should be json[varname] = clipname. Link to comment
luckman212 Posted September 23, 2019 Author Share Posted September 23, 2019 (edited) @deanishe that worked! So the script is: require 'json' json = {} cc = 20 for i in 0..cc do varname = 'clip' + (i).to_s clipname = '{clipboard:' + (i).to_s + '}' json[varname] = clipname end puts({ "alfredworkflow" => { "arg" => "{query}", "variables" => json }}.to_json) So now the script generates "perfect" output, BUT instead of substituting {query} and {clipboard:1} etc. values, Alfred is setting these as literal values. E.g. instead of the actual query or clipboard history contents, I'm getting the literal text "{clipboard:1}". edit: here's a python version of the same script, also suffers from the same problem of non-substituted variables import json, os obj = {} j = {} varlist = {} cc = int(os.getenv('CLIP_COUNT', 3)) for i in range(cc): varname = 'clip' + str(i) clipname = '{clipboard:' + str(i) + '}' varlist[varname] = clipname j['variables'] = varlist j['arg'] = '{query}' obj['alfredworkflow'] = j print json.dumps(obj) Seems impossible that this would be the way the Dynamic Placeholders feature was designed. Do I need to ask @Andrew ? Edited September 23, 2019 by luckman212 Link to comment
luckman212 Posted September 23, 2019 Author Share Posted September 23, 2019 I assume that this is just a limitation. Created a feature request ... Link to comment
deanishe Posted September 23, 2019 Share Posted September 23, 2019 2 hours ago, luckman212 said: Seems impossible that this would be the way the Dynamic Placeholders feature was designed That's exactly how it's designed. From that page: Quote Alfred offers dynamic placeholders, which allow you to insert dynamically-created content when using Snippets and in certain workflow objects. Alfred—quite rightly—doesn't mess with the output from your scripts. What exactly are you trying to achieve? Link to comment
luckman212 Posted September 23, 2019 Author Share Posted September 23, 2019 11 minutes ago, deanishe said: What exactly are you trying to achieve? Trying to create a workflow that references items from the clipboard history (up to 25, 50, or more). So I want to set up the variables programmatically via a loop vs. tediously like { "alfredworkflow" : { "variables" : { ... "clip30" : "{clipboard:30}", "clip31" : "{clipboard:31}", "clip32" : "{clipboard:32}", "clip33" : "{clipboard:33}", "clip34" : "{clipboard:34}", ... } } } Link to comment
deanishe Posted September 23, 2019 Share Posted September 23, 2019 27 minutes ago, luckman212 said: Trying to create a workflow that references items from the clipboard history (up to 25, 50, or more). So I want to set up the variables programmatically via a loop vs. tediously like That's not what you're trying to achieve, that's how you're trying to achieve it. What is the end goal here? Link to comment
luckman212 Posted September 24, 2019 Author Share Posted September 24, 2019 (edited) Ok, well the end goal is a workflow that displays the most recent N clipboard history items and upon selecting one, "types" it to the foreground app by simulating keystrokes (AppleScript `keystroke`). The reason for this to exist is e.g. some websites don't allow copy/paste so you want to "type" something into a field. Or Remote Desktop / ARD / other remote control sessions where a "paste" doesn't always work. This might not be useful for many people but I use it all the time. Here's the workflow as it stands if you want to see: (removed - updated version below...) Edited November 8, 2019 by luckman212 Link to comment
deanishe Posted September 24, 2019 Share Posted September 24, 2019 6 hours ago, luckman212 said: This might not be useful for many people but I use it all the time. I use it quite a lot, too. The best way to get the clipboard history is to read it from Alfred's clipboard database. It's a *little* hacky, but I've seen Andrew recommend people do it this way, so it's pretty safe. Also, it's extremely fast. from contextlib import contextmanager import os import sqlite3 # Number of clipboard items to retrieve COUNT = 10 # Path to clipboard history database # For Alfred 3, replace "Alfred" with "Alfred 3" dbpath = os.path.expanduser('~/Library/Application Support/Alfred/Databases/clipboard.alfdb') @contextmanager def database(path): """Open and close database.""" db = sqlite3.connect(path) yield db db.close() clips = [] with database(dbpath) as db: # each row is a tuple, even though we're only selecting one column rows = db.execute('SELECT item FROM clipboard ORDER BY ts DESC LIMIT ' + str(COUNT)) clips = [row[0] for row in rows] for s in clips: print(s) Dattwood 1 Link to comment
luckman212 Posted September 25, 2019 Author Share Posted September 25, 2019 Thank you @deanishe (and @Andrew of course) Reading from the db does seem like a good way to go. I'll save this thread for reference, when I have a bit more time to work on it. Link to comment
luckman212 Posted November 8, 2019 Author Share Posted November 8, 2019 @deanishe I finally got around to updating this workflow so it queries the sqlite3 db directly. It's a big improvement! Thanks for your help on this. I posted the workflow below ... would love any feedback on things I've done wrong or inefficiently... Type (github) Link to comment
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now