astrofin Posted February 21, 2021 Share Posted February 21, 2021 (edited) I have a js file that ends with msg = JSON.stringify(result) $.NSFileHandle.fileHandleWithStandardOutput.writeData( $.NSString.alloc.initWithString(String(msg)) .dataUsingEncoding($.NSUTF8StringEncoding) ) When I run the script from the terminal, it returns JSON that appears to be correctly formatted for Script Filter. $ ~/Documents/myscript.js list {"items":[{"uid":"1","title":"OptA","autocomplete":"OptA","subtitle":"OptA","arg":"1"},{"uid":"2","title":"OptB","autocomplete":"OptB","subtitle":"OptB","arg":"2"}]} In Alfred, I created a workflow that contains a script filter. `Alfred filters results` is checked, language set to `bin/bash`, and it is configured to run my JS script: ~/Documents/myscript.js list When I type the keyword into Alfred, the workflow is displayed but no list results are returned. Alfred debugger returns ERROR: Script Filter to Script to Notification[Script Filter] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON: Error: Can't convert types. I assume this means that whatever Alfred has received is not recognised as valid JSON, is this correct? Is there a way to interrogate Alfred to inspect what has been received into the script filter? Or is there a better way to debug this error? Edited February 22, 2021 by astrofin Link to comment
deanishe Posted February 21, 2021 Share Posted February 21, 2021 1 hour ago, astrofin said: I assume this means that whatever Alfred has received is not recognised as valid JSON, is this correct? Yes. The JSON is not valid. Going by what you’ve written, you have => at the beginning. If you set Alfred’s debugger to “All information”, it will also show the JSON. In any case, you don’t need to mess about with Objective-C classes. You can just use return JSON.stringify(result) in your run() function. Link to comment
astrofin Posted February 22, 2021 Author Share Posted February 22, 2021 (edited) Thanks deanishe, this has is very useful. I have modified my script to `return JSON.stringify(result)`. When I run the script in terminal, I'm now getting the same JSON that appears to be correctly formatted for Script Filter. $ ~/Documents/myscript.js list {"items":[{"uid":"1","title":"OptA","autocomplete":"OptA","subtitle":"OptA","arg":"1"},{"uid":"2","title":"OptB","autocomplete":"OptB","subtitle":"OptB","arg":"2"}]} However, I'm still getting the same error. I have tracked the source of this to the following line. I'm obtaining the data to populate the list from a csv file that is located in the same directory as script.js. const app = Application.currentApplication(); app.includeStandardAdditions = true // path to the csv file var file = "list.csv"; // Read the file using a specific delimeter and return the results var csv = app.read( Path(fileString) ) When I run this script in the terminal, the current application is able to read the csv. When I run this from Alfred, the script appears to fail at this point. What is the correct way to read the contents of text file? Edited February 22, 2021 by astrofin Link to comment
deanishe Posted February 22, 2021 Share Posted February 22, 2021 I don't know. Could you upload your workflow somewhere and post a link, so we can have a look at it for ourselves? Link to comment
astrofin Posted February 23, 2021 Author Share Posted February 23, 2021 (edited) Thanks deanishe, I appreciate your help with this. The following is a minimal version of the workflow that creates this issue. The workflow is very simple for testing purposes. It consists of only a Script Filter outputting to Large Type. The Script Filer runs my script.js file, which is not located within the workflow package because Alfred is not the only way I access it. The Script Filter script field contains only: ~/Documents/script.js list ~/Documents/script.js looks like this: #!/usr/bin/env osascript -l JavaScript ObjC.import('stdlib') ObjC.import('Foundation') const app = Application.currentApplication(); app.includeStandardAdditions = true function run(argv) { try { return selectCommand(argv) } catch (e) { return e } } function selectCommand(argv) { const cmd = argv[0] if (cmd === 'list') { return list('all') } $.exit(0) } /** * Commands */ // Build the list function list() { // init an empty object to hold the results var result = { 'items': [] } // the csv file var file = "list.csv"; // read the csv file var csv = app.read( Path(file) ) // split the csv string into an array of rows var rows = csv.split('\r\n') // get the headers row var headers = rows[0].split(','); // drop the header row rows.splice(0,1) // iterate through the rows rows.forEach( (row) => { // init an empty object to hold the results var obj = {} // split the row into an array of attributes var currentRow = row.split(',') // iterate through the headers headers.forEach( (header,i) => { // add the key/value pair to the obj container obj[header] = currentRow[i] }) obj["autocomplete"] = obj["title"] obj["subtitle"] = obj["title"] obj["arg"] = obj["uid"] // push the current row object into the results array result.items.push(obj) }) return JSON.stringify(result) } ~/Documents/list.csv looks like this: uid,title 1,OptA 2,OptB Alfred debugger shows Error: Can't convert types. message:Can't convert types., errorNumber:-1700, line:44, column:23, stack:[native code] Line 44 is var csv = app.read( Path(file) ) Is there a better way to read the file? Edited February 23, 2021 by astrofin Link to comment
deanishe Posted February 23, 2021 Share Posted February 23, 2021 Dude, I'm not going to try to rebuild your workflow from scratch just to help you. Please upload it somewhere and post a link. Link to comment
astrofin Posted February 24, 2021 Author Share Posted February 24, 2021 Thanks deanishe I've put everything on GitHub. The repo contains the workflow to be installed into Alfred as usual, plus the files `script.js` and `list.csv` that should be placed in your `~/Documents` directory. Thanks for your help Link to comment
deanishe Posted February 24, 2021 Share Posted February 24, 2021 On 2/22/2021 at 1:04 AM, astrofin said: When I run this script in the terminal, the current application is able to read the csv. When I run this from Alfred, the script appears to fail at this point. Presumably because you’re telling it to read a file called list.csv in the current working directory, so the script will only work if run from the directory containing list.csv. Either move list.csv (and script.js for that matter) into the workflow where the script is looking for it, or change the path in the script to an absolute one. Link to comment
astrofin Posted February 25, 2021 Author Share Posted February 25, 2021 Thanks deanishe Can I please confirm that on your machine you're able to read `list.csv` if called from `script.js` using an absolute path? I've updated `script.js` to use `var file = "~/Documents/list.csv";`. It's still not working for me, which would suggest the problem lies elsewhere rather than with the script. It would be very useful if you're able to confirm this. I note your suggestion to move everything into the workflow. For various reasons, `list.js` needs to be accessible outside the workflow, otherwise I would follow this suggestion. Thanks for taking the time to help! Link to comment
deanishe Posted February 25, 2021 Share Posted February 25, 2021 55 minutes ago, astrofin said: Can I please confirm that on your machine you're able to read `list.csv` if called from `script.js` using an absolute path? I didn't change the script. I put both files inside the workflow, so they're both in the working directory when the workflow is run. 55 minutes ago, astrofin said: var file = "~/Documents/list.csv"; That's not a valid path. ~ for your home directory only works in a shell. You need to write the full path (/Users/blah/Documents/...). Link to comment
astrofin Posted February 27, 2021 Author Share Posted February 27, 2021 Thanks deanishe, appreciate your help with this. It's lead me to the right place. Thanks for confirming that the script works and the full path are required. I had tried full path previously, but there was also another issue preventing it working. I originally created list.csv from the terminal. I hadn't checked file permissions, which were very restrictive and preventing the script reading the file. I've set permissions to something more sensible, and the script now works. Thanks ! 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