CodAlfred - The Alfred Workflow for Coda

Hey,

EdIT: v0.0.2 online now

I’ve created a Coda workflow for Alfred for Mac. Alfred is a powerful replacement for spotlight in OSX. With the workflow you can now:

  • Search & Open Coda Docs
  • Create a new Coda Doc
  • Quickly open your Coda Doc list
  • Open the Coda Formula list
  • Open the Coda Community

demo

You can also search by keyword if you type after the 'cd ’ command (not visible in the video)

You can download the workflow here
Readme file and source code can be found on Github

Installation:

  1. Download the workflow
  2. Double click the file that you just downloaded
  3. Insert your Coda API Token in the ‘apikey’ values field (How to find your API Key)
  4. Complete the installation dialog

I’ve only tested it on my own mac. I hope everything works :slight_smile: I’d appreciate if someone could test it and give me feedback :raised_hands:

9 Likes

I absolutely swear by Alfred so I’m all over this. :slight_smile: Slight teething problem though in that it doesn’t work for me (yet!) I notice the script includes your Mac username - I’ve swapped it for mine but it still doesn’t work.

When I type cdn and then start typing a name, it briefly says “Creating…” and then disappears to be replaced with my fallbacks (Google etc.)

Hey @Nick_Milner,
thank you for your feedback :smiley: It is my first workflow, but I really want to make it work for everyone. Maybe you can help me out finding whats wrong.

Can you tell me where you found my Mac username? The BundleID is just a unique name that will be converted to an ID (as far as I know right now), so this can stay the same.

Also inside the script, there is $coda = new \danielstieber\CodAlfred\CodAlfred($key); which should not be altered! This is the PHP namespace, where the script finds the function in the class, that handles all operations. If you change this, the script should definitely stop working :thinking:

On the top right corner of the workflow page should be a little bug icon. If you click it, the debug console opens. If you now open alfred with you shortcut and use the workflow, you should get feedback there. So e.g. if you put in ‘cd asdf’ and it does not work, you should theoretically get an error there. Can you maybe look, if an error pops up?

Ha, oops. :slight_smile: Ok, I’ve put that back (yeah, I don’t know anything about Alfred workflows!)

Ok, when I type CDN I get the following:

[20:53:36.519] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Queuing argument ''

[20:53:37.394] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Script with argv '' finished

[20:53:37.398] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Warning: Invalid argument supplied for foreach() in /Users/nmilner/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041/src/CodAlfred.php on line 51

{"items":[]}

[20:53:37.399] ERROR: CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON:

Warning: Invalid argument supplied for foreach() in /Users/nmilner/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041/src/CodAlfred.php on line 51

{"items":[]}

Thanks!

If I type “CD” I get the following error:

[21:00:38.608] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Queuing argument ''

[21:00:39.604] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Script with argv '' finished

[21:00:39.607] CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] Warning: Invalid argument supplied for foreach() in /Users/nmilner/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041/src/CodAlfred.php on line 51

{"items":[]}

[21:00:39.607] ERROR: CodAlfred[[Script Filter](alfredpreferences:workflows%3Eworkflow%3Euser.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041%3E8D3776F9-A62C-480A-8D6F-70F4D167416A)] JSON error: JSON text did not start with array or object and option to allow fragments not set. in JSON:

Warning: Invalid argument supplied for foreach() in /Users/nmilner/Library/Application Support/Alfred/Alfred.alfredpreferences/workflows/user.workflow.8F2382C1-BFA6-4E82-8634-E23450CBF041/src/CodAlfred.php on line 51

{"items":[]}

Hey @Nick_Milner , thanks a lot for sharing the error.

Can you re-check if you have put in the right API key? There is another button that opens the ‘variables’, where you can update it. (it is the first button that looks like this: [x])
I can reproduce the same error when I remove my API key. Does not mean that it is the only reason for that error, but maybe it helps.

Hmm, the api key variable was blank when I double-checked but I was sure I entered it originally. Sorry for being the world’s worst tester! Anyway, it all now works perfectly and will be my new way of accessing Coda from now on. Thanks!

A benefit is I can now remove the Chrome add-in which seems to get in the way more than it helps.

1 Like

I‘m happy that we found the solution! :slight_smile:

1 Like

Hi Daniel, would it be possible to add a feature such that if you enter CD without a parameter it takes you to the “All Docs” folder?

I’ve updated the Workflow to 0.0.2 with a bug fix and new features.

Thanks for the idea @Nick_Milner, I’ve added that feature. I recognized that it is slow, because you have to wait until the list is loaded to just open Coda. Thats why there are now not one – not two – but three fresh & powerful commands to use :boom:

  • cda | Open your Coda Doc list (no wait time)
  • cdf | Open the Coda Formula list
  • cdc | Open your favourite community

The updated can be downloaded here. Just doubeclick the file and Alfred will update it.

I will update the first post of this trhead with this link as well.

4 Likes

That’s perfect, thanks!

Fantastic! This is exactly what I was trying to create for myself. Thank you for saving me a bunch of time, Daniel.

1 Like

Hey @Thomas_Hils,

cool :slight_smile: Let me know if you have feedback!

I think of adding a ‘cache’ to avoid a new http request for every letter. This should boost the performance when searching docs. Maybe I’ll find the time tomorrow.

2 Likes

This is amazing! I tried adding a new function to create a doc from a source doc. Let’s say the source doc’s ID is abcDEF123.

This is what I pasted into CodAlfred.php:

/**
	 * Creates a copy of a Coda Doc
	 * 
	 * @param string $filename
	 * @return string
	 */
	public function createCopy($filename)
	{
		$doc = $this->coda->createDoc($filename);
		$this->workflow->result()
		->uid($doc['id'])
		->title($doc['name'])
		->sourceDoc('abcDEF123')
		->autocomplete($doc['name'])
		->subtitle($subtitle)
		->arg($doc['browserLink'])
		->quicklookurl($doc['browserLink'])
		->valid(true);
		return $this->workflow->output();
	}
}

Then I opened the workflow in Alfred, copied the “cdn > Open URL” pair, pasted it, changed the keyword to “cdx,” and changed the script to call the new “CreateCopy” function:

It didn’t work. Needless to say, I don’t know PHP and I’ve never created a workflow. Do you know if there’s an easy to way to add a function that creates a new document from a source document?

Thanks for your time!

1 Like

Hey @David_Busis,
the method “createDoc” of the CodaPHP library that I’ve made and also used in CodAlfred allows a second parameter ‘Doc ID’ as source to copy a doc.

So if you replace your createCopy with this code, it should work:

CodAlfred.php

	/**
	 * Creates a Copy of the Doc 'abcDEF123'
	 * 
	 * @param string $filename
	 * @return string
	 */
	public function createCopy($filename)
	{
		$doc = $this->coda->createDoc($filename, 'abcDEF123');
		$this->workflow->result()
		->uid($doc['id'])
		->title($doc['name'])
		->autocomplete($doc['name'])
		->subtitle($subtitle)
		->arg($doc['browserLink'])
		->quicklookurl($doc['browserLink'])
		->valid(true);
		return $this->workflow->output();
	}

The cdx part you’ve made should be fine.
I have not tried it, maybe you can give it a shot? :slight_smile:

Thanks so much! I tried it, and the new code doesn’t work. It also breaks the find and create functions. The CDX part that’s visible in Alfred doesn’t break anything. If I leave it there (as in picture below) but delete the createCopy function, everything works as normal.

I’ve tried it now and it worked perfectly fine.

Sounds like you have a syntax error in your PHP file, that’s why the whole file doesn’t work any longer. Have you used the and around the DocID? Or have you accidentally deleted the last }?

Here is the whole working file including createCopy:

Expand
<?php
namespace danielstieber\CodAlfred;

use Alfred\Workflows\Workflow;
use CodaPHP\CodaPHP;

/**
 * CodAlfred Workflow
 * 
 * CodAlfred is a basic workflow to open Docs from Coda (https://www.coda.io) with Alfred.
 * The workflow uses the CodaPHP library, that is build on the Coda API (Beta) (https://coda.io/developers/apis/v1beta1).
 * The Coda API is still in beta. Use on your own risk.
 * 
 * This file is licensed under the MIT license.
 */
class CodAlfred
{
	/**
	 * @var string $apiToken
	 */
	protected $apiToken;

    /**
     * @var Workflow
     */
    private $workflow;

	/**
	 * Setup the Workflow and access the Coda API via CodaPHP
	 */
	public function __construct($apiToken)
	{
		$this->workflow = new Workflow();
		$this->coda = new CodaPHP($apiToken);
	}

	/**
	 * Searches the Coda doc list based on a the query
	 * 
	 * @param string $query
	 * @return string
	 */
	public function find($query)
	{
		$now = time();
		if(empty(trim($query))) { // if no arg is given
			$result = $this->coda->listDocs(); // get all docs
			$this->workflow->result() // adds option to open coda in browser
				->uid('1') // lowest ID, so it is ranked first
				->title('Open Coda in your Browser')
				->autocomplete('Open Coda in your Browser')
				->subtitle($subtitle)
				->arg('https://coda.io/docs')
				->quicklookurl('https://coda.io/docs')
				->valid(true);
		} else {
			$result = $this->coda->listDocs(['query' => $query]);
		}
		foreach ($result['items'] as $doc) {
			$updated = strtotime($doc['updatedAt']);
			$subtitle = 'Last modified: '.date('d.m.Y h:m', $updated);
			$this->workflow->result()
				->uid($now - $updated) // id is current timestamp - doc timestamp
				->title($doc['name'])
				->autocomplete($doc['name'])
				->subtitle($subtitle)
				->arg($doc['browserLink'])
				->quicklookurl($doc['browserLink'])
				->valid(true);
		}
		$this->workflow->sortResults('asc', 'uid'); // ranks docs with latest update first
        return $this->workflow->output();
	}

	/**
	 * Creates a new Coda Doc
	 * 
	 * @param string $filename
	 * @return string
	 */
	public function create($filename)
	{
		$doc = $this->coda->createDoc($filename);
		$this->workflow->result()
		->uid($doc['id'])
		->title($doc['name'])
		->autocomplete($doc['name'])
		->subtitle($subtitle)
		->arg($doc['browserLink'])
		->quicklookurl($doc['browserLink'])
		->valid(true);
		return $this->workflow->output();
	}
	/**
	 * Copies a Coda Doc
	 * 
	 * @param string $filename
	 * @return string
	 */
	public function createCopy($filename)
	{
		$doc = $this->coda->createDoc($filename, '5asfe8cd');
		$this->workflow->result()
		->uid($doc['id'])
		->title($doc['name'])
		->autocomplete($doc['name'])
		->subtitle($subtitle)
		->arg($doc['browserLink'])
		->quicklookurl($doc['browserLink'])
		->valid(true);
		return $this->workflow->output();
	}
}
1 Like

Ah! I had just pasted my function below the final bracket that closed class CodAlfred. It works now!

Thank you so much! This is a great time saver.

1 Like