diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..382b46b
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,17 @@
+# EditorConfig is awesome: http://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Tab indentation
+[*]
+indent_style = tab
+indent_size = 2
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+# The indent size used in the `package.json` file cannot be changed
+# https://github.com/npm/npm/pull/3180#issuecomment-16336516
+[{.travis.yml,npm-shrinkwrap.json,package.json}]
+indent_style = space
+indent_size = 2
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1ce0a74
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,4 @@
+out
+node_modules
+.vscode-test
+*.vsix
diff --git a/.vscode/launch.json b/.vscode/launch.json
new file mode 100644
index 0000000..c696e43
--- /dev/null
+++ b/.vscode/launch.json
@@ -0,0 +1,32 @@
+// A launch configuration that compiles the extension and then opens it inside a new window
+{
+ "version": "0.1.0",
+ "configurations": [
+ {
+ "name": "Launch Extension",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": ["--extensionDevelopmentPath=${workspaceRoot}" ],
+ "stopOnEntry": false,
+ "sourceMaps": true,
+ "outFiles": [
+ "${workspaceRoot}/out/src/**/*.js"
+ ],
+ "preLaunchTask": "npm"
+ },
+ {
+ "name": "Launch Tests",
+ "type": "extensionHost",
+ "request": "launch",
+ "runtimeExecutable": "${execPath}",
+ "args": ["--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/test" ],
+ "stopOnEntry": false,
+ "sourceMaps": true,
+ "outFiles": [
+ "${workspaceRoot}/out/test/**/*.js"
+ ],
+ "preLaunchTask": "npm"
+ }
+ ]
+}
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..7877e3f
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,10 @@
+// Place your settings in this file to overwrite default and user settings.
+{
+ "files.exclude": {
+ "out": false // set this to true to hide the "out" folder with the compiled JS files
+ },
+ "search.exclude": {
+ "out": true // set this to false to include "out" folder in search results
+ },
+ "typescript.tsdk": "./node_modules/typescript/lib" // we want to use the TS server from our node_modules folder to control its version
+}
\ No newline at end of file
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
new file mode 100644
index 0000000..fb7f662
--- /dev/null
+++ b/.vscode/tasks.json
@@ -0,0 +1,30 @@
+// Available variables which can be used inside of strings.
+// ${workspaceRoot}: the root folder of the team
+// ${file}: the current opened file
+// ${fileBasename}: the current opened file's basename
+// ${fileDirname}: the current opened file's dirname
+// ${fileExtname}: the current opened file's extension
+// ${cwd}: the current working directory of the spawned process
+
+// A task runner that calls a custom npm script that compiles the extension.
+{
+ "version": "0.1.0",
+
+ // we want to run npm
+ "command": "npm",
+
+ // the command is a shell script
+ "isShellCommand": true,
+
+ // show the output window only if unrecognized errors occur.
+ "showOutput": "silent",
+
+ // we run the custom script "compile" as defined in package.json
+ "args": ["run", "compile", "--loglevel", "silent"],
+
+ // The tsc compiler is started in watching mode
+ "isWatching": true,
+
+ // use the standard tsc in watch mode problem matcher to find compile problems in the output.
+ "problemMatcher": "$tsc-watch"
+}
\ No newline at end of file
diff --git a/.vscodeignore b/.vscodeignore
new file mode 100644
index 0000000..93e28ff
--- /dev/null
+++ b/.vscodeignore
@@ -0,0 +1,9 @@
+.vscode/**
+typings/**
+out/test/**
+test/**
+src/**
+**/*.map
+.gitignore
+tsconfig.json
+vsc-extension-quickstart.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..63d3c92
--- /dev/null
+++ b/README.md
@@ -0,0 +1,32 @@
+# JMESPath for Visual Studio Code
+
+JMESPath (pronounced "james path") is a query language for JSON which allows one to extract and transform elements from a JSON document.
+
+This extension lets you test JMESPath expressions from within Visual Studio Code.
+
+For more information about JMESPath, please visit [here](http://jmespath.org)
+
+## Features
+
+This extension depends on the [JavaScript implementation of JMESPath](https://github.com/jmespath/jmespath.js) which is fully compliant with latest [specification](http://jmespath.org/specification.html).
+
+![JMESPath Example](images/jmespath-example.gif)
+
+## How to use this extension
+
+This extension adds `JMESPath: Query JSON` command to the command palette.
+
+To use the extension:
+
+- Open a JSON document
+- Run `JMESPath: Query JSON` command from command palette (`F1` on Windows or `Cmd+Shift+P` on Mac)
+- Enter JMESPath expression
+- Expression output will be shown in `JMESPath Output` window
+
+## Release Notes
+
+### 0.0.1
+
+- Initial release
+
+
diff --git a/images/jmespath-example.gif b/images/jmespath-example.gif
new file mode 100644
index 0000000..9e020aa
Binary files /dev/null and b/images/jmespath-example.gif differ
diff --git a/images/jmespath.png b/images/jmespath.png
new file mode 100644
index 0000000..1c8c1ac
Binary files /dev/null and b/images/jmespath.png differ
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6db064f
--- /dev/null
+++ b/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "vscode-jmespath",
+ "displayName": "JMESPath for VSCode",
+ "description": "Evaluate JMESPath queries within Visual Studio Code",
+ "version": "0.0.1",
+ "main": "./out/src/jmespathMain",
+ "scripts": {
+ "vscode:prepublish": "node ./node_modules/vscode/bin/compile",
+ "compile": "node ./node_modules/vscode/bin/compile -watch -p ./",
+ "postinstall": "node ./node_modules/vscode/bin/install",
+ "test": "node ./node_modules/vscode/bin/test"
+ },
+ "devDependencies": {
+ "@types/chai": "^3.4.34",
+ "@types/sinon": "^1.16.34",
+ "chai": "^3.5.0",
+ "sinon": "^1.17.7",
+ "tslint": "^4.2.0",
+ "typescript": "^2.1.4",
+ "vscode": "^0.11.0"
+ },
+ "dependencies": {
+ "jmespath": "^0.15.0"
+ },
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/j--wong/vscode-jmespath.git"
+ },
+ "publisher": "joshwong",
+ "icon": "images/jemspath.png",
+ "galleryBanner": {
+ "color": "#13254a",
+ "theme": "dark"
+ },
+ "private": true,
+ "engines": {
+ "vscode": "^1.0.0"
+ },
+ "categories": [
+ "Other"
+ ],
+ "keywords": [
+ "jmespath",
+ "json",
+ "query"
+ ],
+ "activationEvents": [
+ "onLanguage:json",
+ "onCommand:jmespath.query"
+ ],
+ "contributes": {
+ "commands": [
+ {
+ "title": "JMESPath: Query JSON",
+ "command": "jmespath.query"
+ }
+ ],
+ "configuration": {
+ "title": "",
+ "properties": {
+ "jmespath.rememberRecentExpressions": {
+ "type": "boolean",
+ "default": true,
+ "description": "Specify whether or not to record recently entered expressions"
+ },
+ "jmespath.maxRecentExpressionsToRemember": {
+ "type": "integer",
+ "default": 25,
+ "description": "Specify the number of expressions to remember"
+ }
+ }
+ }
+ }
+}
diff --git a/src/jmespathMain.ts b/src/jmespathMain.ts
new file mode 100644
index 0000000..d5705a6
--- /dev/null
+++ b/src/jmespathMain.ts
@@ -0,0 +1,14 @@
+"use strict";
+
+import * as vscode from "vscode";
+import { queryJson } from "./jmespathQuery";
+
+export function activate(context: vscode.ExtensionContext) {
+ context.subscriptions.push(
+ vscode.commands.registerTextEditorCommand("jmespath.query",
+ (textEditor: vscode.TextEditor, edit: vscode.TextEditorEdit) => {
+ queryJson(context);
+ }
+ )
+ );
+}
diff --git a/src/jmespathQuery.ts b/src/jmespathQuery.ts
new file mode 100644
index 0000000..5fe3a8b
--- /dev/null
+++ b/src/jmespathQuery.ts
@@ -0,0 +1,45 @@
+import * as vscode from "vscode";
+let jmespath = require("jmespath");
+
+let outputChannel = vscode.window.createOutputChannel("JMESPath Output");
+
+export function queryJson(context: vscode.ExtensionContext) {
+ let editor = vscode.window.activeTextEditor;
+
+ if (editor.document.languageId !== "json") {
+ vscode.window.showInformationMessage("Please open a JSON document.");
+ return;
+ }
+
+ let options: vscode.InputBoxOptions = {
+ prompt: "Enter JMESPath expression",
+ placeHolder: "JMESPath expression"
+ };
+
+ vscode.window.showInputBox(options).then((expression) => {
+ if (expression.trim().length === 0) {
+ return;
+ }
+
+ try {
+ jmespath.compile(expression);
+ }
+ catch (e) {
+ vscode.window.showErrorMessage(`${e.message}`);
+ return;
+ }
+
+ let data = vscode.window.activeTextEditor.document.getText();
+ try {
+ let jsonData = JSON.parse(data);
+ let searchResult = jmespath.search(jsonData, expression);
+
+ outputChannel.clear();
+ outputChannel.append(JSON.stringify(searchResult, null, " "));
+ outputChannel.show();
+ } catch (e) {
+ vscode.window.showErrorMessage(`${e.message}`);
+ return;
+ }
+ });
+}
diff --git a/src/util/environment.ts b/src/util/environment.ts
new file mode 100644
index 0000000..5113382
--- /dev/null
+++ b/src/util/environment.ts
@@ -0,0 +1,22 @@
+import * as path from "path";
+import * as vscode from "vscode";
+
+export default class Environment {
+ private context: vscode.ExtensionContext;
+
+ constructor(context: vscode.ExtensionContext) {
+ this.context = context;
+ }
+
+ public getHomeDir(): string {
+ return process.env[(process.platform === "win32") ? "USERPROFILE" : "HOME"];
+ }
+
+ public isInsiders(): boolean {
+ return /insiders/.test(this.context.asAbsolutePath(""));
+ }
+
+ public getExtensionDir(): string {
+ return path.join(this.getHomeDir(), this.isInsiders() ? ".vscode-insiders" : ".vscode", "extensions");
+ }
+}
diff --git a/test/index.ts b/test/index.ts
new file mode 100644
index 0000000..c7c6237
--- /dev/null
+++ b/test/index.ts
@@ -0,0 +1,8 @@
+let testRunner = require("vscode/lib/testrunner");
+
+testRunner.configure({
+ ui: "bdd",
+ useColors: true
+});
+
+module.exports = testRunner;
diff --git a/test/jmespathMain.test.ts b/test/jmespathMain.test.ts
new file mode 100644
index 0000000..0ea5bf4
--- /dev/null
+++ b/test/jmespathMain.test.ts
@@ -0,0 +1,44 @@
+import * as vscode from "vscode";
+import * as jmespathMain from "../src/jmespathMain";
+import * as assert from "assert";
+import * as sinon from "sinon";
+import chai = require("chai");
+
+let expect = chai.expect;
+
+describe("JMESPath extension", () => {
+ let extensionId = "joshwong.vscode-jmespath";
+
+ describe("#activate()", () => {
+ let context: vscode.ExtensionContext;
+ let stubTextEditorCommand: sinon.SinonStub;
+
+ beforeEach(() => {
+ context = {
+ subscriptions: [],
+ workspaceState: null,
+ globalState: null,
+ extensionPath: null,
+ asAbsolutePath: sinon.stub()
+ };
+ stubTextEditorCommand = sinon.stub(vscode.commands, "registerTextEditorCommand");
+ });
+
+ afterEach(() => {
+ stubTextEditorCommand.restore();
+ });
+
+ it("should register 'jmespath.query' command", sinon.test(() => {
+ jmespathMain.activate(context);
+ expect(stubTextEditorCommand.calledWith("jmespath.query")).to.be.true;
+ }));
+
+ it("should add disposable command to subscriptions array", sinon.test(() => {
+ jmespathMain.activate(context);
+
+ expect(context.subscriptions).to.not.be.empty;
+ expect(context.subscriptions.length).to.equals(1);
+ }));
+ });
+
+});
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..c438876
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "target": "es5",
+ "outDir": "out",
+ "noLib": true,
+ "sourceMap": true,
+ "rootDir": ".",
+ "moduleResolution": "node"
+ },
+ "exclude": [
+ "node_modules",
+ ".vscode-test"
+ ]
+}
diff --git a/tslint.json b/tslint.json
new file mode 100644
index 0000000..994841f
--- /dev/null
+++ b/tslint.json
@@ -0,0 +1,55 @@
+{
+ "rules": {
+ "class-name": true,
+ "comment-format": [
+ true,
+ "check-space"
+ ],
+ "indent": [
+ true,
+ "tabs"
+ ],
+ "no-duplicate-variable": true,
+ "no-eval": true,
+ "no-internal-module": true,
+ "no-trailing-whitespace": true,
+ "no-var-keyword": true,
+ "one-line": [
+ true,
+ "check-open-brace",
+ "check-whitespace"
+ ],
+ "quotemark": [
+ true,
+ "double"
+ ],
+ "semicolon": [
+ "always"
+ ],
+ "triple-equals": [
+ true,
+ "allow-null-check"
+ ],
+ "typedef-whitespace": [
+ true, {
+ "call-signature": "nospace",
+ "index-signature": "nospace",
+ "parameter": "nospace",
+ "property-declaration": "nospace",
+ "variable-declaration": "nospace"
+ }
+ ],
+ "variable-name": [
+ true,
+ "ban-keywords"
+ ],
+ "whitespace": [
+ true,
+ "check-branch",
+ "check-decl",
+ "check-operator",
+ "check-separator",
+ "check-type"
+ ]
+ }
+}
\ No newline at end of file
diff --git a/typings/node.d.ts b/typings/node.d.ts
new file mode 100644
index 0000000..5ed7730
--- /dev/null
+++ b/typings/node.d.ts
@@ -0,0 +1 @@
+///
\ No newline at end of file
diff --git a/typings/sinon.d.ts b/typings/sinon.d.ts
new file mode 100644
index 0000000..20da980
--- /dev/null
+++ b/typings/sinon.d.ts
@@ -0,0 +1,2 @@
+///
+///
diff --git a/typings/vscode-typings.d.ts b/typings/vscode-typings.d.ts
new file mode 100644
index 0000000..5590dc8
--- /dev/null
+++ b/typings/vscode-typings.d.ts
@@ -0,0 +1 @@
+///