Skip to content

Instantly share code, notes, and snippets.

@cpriest
Last active January 21, 2017 16:29
Show Gist options
  • Save cpriest/2d2089396ee66f5be25bde9bd1a0c8a6 to your computer and use it in GitHub Desktop.
Save cpriest/2d2089396ee66f5be25bde9bd1a0c8a6 to your computer and use it in GitHub Desktop.
The way hain-plugin-psl works...

From the start I knew what I wanted to build and the built-in preferences system was too limited to express the configuration, so I decided to go with json5.

It is split into two notions, the first is a pattern. Patterns were the first notion in the project and were a simple way to specify a regular expression pattern and what it would result in.

This is a sample for an npmjs.com search:

{
	patterns: [
		{
			pattern: '^npm (.*)$',
			cmd:     'https://www.npmjs.com/search?q=$1',
			title:   'Search npmjs for "$1"',
			desc:    '',
			icon:    'https://www.npmjs.com/favicon.ico',
		}
	]
}

You can see above, the pattern activates with input starting with "npm" and whatever follows after the first space is captured. The pattern captures can be used in any of the following cmd/title/desc/icon fields if desired.

The second concept is that of a "provider." The current major provider is for github. Here is the pattern for the github provider:

{
	pattern: '^(@gh_repos)',
	cmd:     '${html_url}',
	title:	 '${prov.title}', 	// {prov.title} maps to provider -> {title}
	desc:    '${description}',
	icon:    '',
}

So with this example, any input is checked against the results of the provider @gh_repos. Here is a simplified provider definition for gh_repos:

{
	gh_repos: {
		type:    'Github',

		// This specifies the Github search URI to be used for this result set
		// 		@see https://developer.github.com/v3/search/#search-repositories
		uri:   '/search/repositories',

		title: '${full_name} : GitHub Repository',

		queries: [
			'user:cpriest user:resgen'
		],
	},
}

The above provider definition, at startup, queries github's api at /search/repositories with the queries specified. This results in a set of properties. For purposes of this example we'll say this returns a single result such as this:

{
	"id": 3081286,
	"name": "Tetris",
	"full_name": "dtrupenn/Tetris",
	"html_url": "https://github.com/dtrupenn/Tetris",
	"description": "A C implementation of Tetris using Pennsim through LC4",
	"owner": {
		"login": "dtrupenn",
		"type": "user"
	}
}

I'm assuming you're familiar with ES2015 template literals, they let you do nifty things. So you see the title parameter of the provider references ${full_name} so this first API result will have the search title become "dtrupenn/Tetris : GitHub Repository"

When the user input from the pattern matches this title, the cmd/title/desc/icon from the pattern are resolved with the original API result. So if the user typed in dtrupenn/Tet, the resulting res.add() call would end up being:

{
	"id":		"https://github.com/dtrupenn/Tetris",
	"title":	"dtrupenn/Tetris : GitHub Repository",
	"desc":		"A C implementation of Tetris using Pennsim through LC4",
	"icon":		"",
	"payload":	{ ... },
}

While the above is a simple usage of template literals, it could be much more sophisticated. For example the pattern title could be: "${full_name.replace(/.+?\//, ''} by ${owner.type} ${owner.login} (ID#${id})" which would mean when matched against this entry, the res.add() title would become: "Tetris by user dtrupenn (ID#3081286"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment