├── .gitignore ├── .vscode └── launch.json ├── .vscodeignore ├── README.md ├── images └── robotframework.png ├── package.json ├── robotframework.configuration.json ├── src └── extension.ts ├── syntaxes └── robot.tmLanguage ├── tsconfig.json ├── typings ├── node.d.ts └── vscode-typings.d.ts └── vsc-extension-quickstart.md /.gitignore: -------------------------------------------------------------------------------- 1 | out 2 | node_modules -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | // A launch configuration that launches the extension inside a new window 2 | { 3 | "version": "0.1.0", 4 | "configurations": [ 5 | { 6 | "name": "Launch Extension", 7 | "type": "extensionHost", 8 | "request": "launch", 9 | "runtimeExecutable": "${execPath}", 10 | "args": ["--extensionDevelopmentPath=${workspaceRoot}" ], 11 | "sourceMaps": true, 12 | "outDir": "${workspaceRoot}/out/src" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscodeignore: -------------------------------------------------------------------------------- 1 | .vscode/** 2 | typings/** 3 | out/test/** 4 | test/** 5 | src/** 6 | **/*.map 7 | .gitignore 8 | tsconfig.json 9 | vsc-extension-quickstart.md 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Robot Framework language support for Visual Studio Code 2 | 3 | This Visual Studio Code extension supports editing .robot files. 4 | 5 | Supported features are: 6 | 7 | - Syntax highlighting 8 | - Command 'Robot: Search Keyword' 9 | 10 | Syntax highlighting is self-explanatory, and only supports files with extension `.robot`. 11 | It's based on [TextMate bundle](https://bitbucket.org/jussimalinen/robot.tmbundle/wiki/Home) by Jussi Malinen. 12 | 13 | Keyword Search requires you to generate the documentation xml files for the libraries you are using, 14 | with [libdoc](http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#libdoc). 15 | 16 | You can copy the xml files for a selection of standard libraries from [robotframework-libdocs project](https://github.com/vivainio/robotframework-libdocs), if you don't want to generate them yourself. 17 | 18 | If the .robot file you are editing has these libary references: 19 | 20 | ``` 21 | Library Foo 22 | Library Bar 23 | ``` 24 | 25 | ...keyword search will look for files Foo.xml and Bar.xml within the PYTHONPATH (same mechanism as used by RIDE). 26 | 27 | Installation: install from Visual Studio Code marketplace, name of the extension is `robotframework`. 28 | 29 | Author: Ville M. Vainio 30 | 31 | License: MIT 32 | -------------------------------------------------------------------------------- /images/robotframework.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vivainio/robotframework-vscode/45a2414d76fa509da0316392fa53564291012b66/images/robotframework.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "robotframework", 3 | "displayName": "robotframework", 4 | "description": "Robot Framework support", 5 | "version": "0.1.2", 6 | "publisher": "vivainio", 7 | "icon": "images/robotframework.png", 8 | "license": "MIT", 9 | "engines": { 10 | "vscode": "^0.10.6" 11 | }, 12 | "categories": [ 13 | "Languages" 14 | ], 15 | "activationEvents": [ 16 | "onCommand:extension.searchRobotKeyword" 17 | ], 18 | "main": "./out/src/extension", 19 | "contributes": { 20 | "commands": [ 21 | { 22 | "command": "extension.searchRobotKeyword", 23 | "title": "Robot: Search Keyword" 24 | } 25 | ], 26 | "languages": [ 27 | { 28 | "id": "robot", 29 | "aliases": [ 30 | "robotframework" 31 | ], 32 | "extensions": [ 33 | ".robot" 34 | ], 35 | "configuration": "./robotframework.configuration.json" 36 | } 37 | ], 38 | "grammars": [ 39 | { 40 | "language": "robot", 41 | "scopeName": "text.robot", 42 | "path": "./syntaxes/robot.tmLanguage" 43 | } 44 | ] 45 | }, 46 | "scripts": { 47 | "vscode:prepublish": "node ./node_modules/vscode/bin/compile", 48 | "compile": "node ./node_modules/vscode/bin/compile -watch -p ./", 49 | "postinstall": "node ./node_modules/vscode/bin/install" 50 | }, 51 | "devDependencies": { 52 | "typescript": "^1.7.5", 53 | "vscode": "^0.11.0" 54 | }, 55 | "dependencies": { 56 | "sax": "^1.2.1", 57 | "xml2js": "^0.4.16" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /robotframework.configuration.json: -------------------------------------------------------------------------------- 1 | { 2 | "comments": { 3 | // symbol used for single line comment. Remove this entry if your language does not support line comments 4 | "lineComment": "#" 5 | // symbols used for start and end a block comment. Remove this entry if your language does not support block comments 6 | }, 7 | // symbols used as brackets 8 | "brackets": [ 9 | ["{", "}"], 10 | ["[", "]"], 11 | ["(", ")"] 12 | ] 13 | } -------------------------------------------------------------------------------- /src/extension.ts: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | // The module 'vscode' contains the VS Code extensibility API 3 | // Import the module and reference it with the alias vscode in your code below 4 | import * as vscode from 'vscode'; 5 | import fs = require('fs'); 6 | import path = require('path'); 7 | const sax = require('sax'); 8 | 9 | // this method is called when your extension is activated 10 | // your extension is activated the very first time the command is executed 11 | function findAll(re: RegExp, haystack: string) { 12 | const res: RegExpExecArray[] = []; 13 | while (1) { 14 | const match = re.exec(haystack); 15 | if (!match) { 16 | break; 17 | } 18 | res.push(match); 19 | } 20 | return res; 21 | } 22 | 23 | class RfModel { 24 | kws: {[kw: string]: string[]} = {}; 25 | parse(cont: string) { 26 | const parser = sax.parser(false); 27 | let current_kw = ''; 28 | let current_args = []; 29 | let current_text = ''; 30 | parser.onopentag = (node) => { 31 | if (node.name == 'KW') { 32 | current_kw = node.attributes.NAME; 33 | current_args = []; 34 | } 35 | if (node.name == 'ARG') { 36 | current_text = ''; 37 | } 38 | } 39 | parser.ontext = (text) => current_text = text; 40 | parser.onclosetag = (tag => { 41 | if (tag == 'ARG') { 42 | current_args.push(current_text); 43 | } 44 | if (tag == "KW") { 45 | this.kws[current_kw] = current_args 46 | } 47 | }); 48 | parser.write(cont); 49 | } 50 | 51 | keywordNames() { 52 | return Object.keys(this.kws); 53 | } 54 | 55 | } 56 | function parseDocFiles(fnames: string[]) { 57 | const keywords = []; 58 | const model = new RfModel(); 59 | fnames.forEach ( (fn) => { 60 | const cont = fs.readFileSync(fn, 'utf8'); 61 | const re = //g; 62 | const matches = findAll(re, cont).map(el => el[1]); 63 | model.parse(cont); 64 | keywords.push(...matches); 65 | 66 | }) 67 | return model; 68 | } 69 | 70 | function findDocFiles(dirs: string[], fnames: string[]) { 71 | const found = []; 72 | dirs.forEach( (d) => { 73 | const tries = fnames.map( (fn) => path.join(d, fn) + ".xml"); 74 | const exists = tries.filter((fn) => fs.existsSync(fn)); 75 | found.push(...exists); 76 | }); 77 | return found; 78 | } 79 | 80 | function getPythonPath() { 81 | const env: string = process.env.PYTHONPATH; 82 | const parts = env.split(path.delimiter); 83 | return parts; 84 | } 85 | 86 | function findLibRefs(doc: string) { 87 | const hits = findAll(/Library\s+?(\w+)/g, doc); 88 | return hits.map(h => h[1]); 89 | } 90 | 91 | export function activate(context: vscode.ExtensionContext) { 92 | let model: RfModel = null; 93 | //let keywords = null; 94 | 95 | 96 | const disposable = vscode.commands.registerCommand('extension.searchRobotKeyword', () => { 97 | if (!model) { 98 | const pp = getPythonPath(); 99 | const libRefs = findLibRefs(vscode.window.activeTextEditor.document.getText()); 100 | 101 | const docFiles = findDocFiles(pp, libRefs); 102 | model = parseDocFiles(docFiles); 103 | } 104 | 105 | vscode.window.showQuickPick(model.keywordNames()).then( (selected) => { 106 | const editor = vscode.window.activeTextEditor; 107 | 108 | editor.edit((editBuilder) => { 109 | const pos = new vscode.Position (editor.selection.active.line, editor.selection.active.character); 110 | const args = model.kws[selected].map(arg => arg.indexOf('=') == -1 ? arg + '=' : arg ) 111 | 112 | const output = selected + ' ' + args.join(' '); 113 | 114 | editBuilder.insert(pos, output); 115 | }); 116 | }); 117 | }); 118 | 119 | context.subscriptions.push(disposable); 120 | } 121 | 122 | // this method is called when your extension is deactivated 123 | export function deactivate() { 124 | } -------------------------------------------------------------------------------- /syntaxes/robot.tmLanguage: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | comment 6 | 7 | Robot Framework syntax highlighting for txt format. 8 | 9 | fileTypes 10 | 11 | robot 12 | 13 | keyEquivalent 14 | ^~R 15 | name 16 | robottxt 17 | patterns 18 | 19 | 20 | match 21 | (^\*\*\*.*?\*\*\*)|((?<=^\|)\s+\*\*\*.*?\*\*\*) 22 | name 23 | string.robot.header 24 | 25 | 26 | match 27 | \[.*?\] 28 | name 29 | storage.type.method.robot 30 | 31 | 32 | match 33 | (\$\{.*?\})|(@\{.*?\}) 34 | name 35 | storage.type.method.robot 36 | 37 | 38 | begin 39 | ((^\s*)|(\s\s)|\t)(?<!\\)# 40 | end 41 | $ 42 | name 43 | comment.robot 44 | 45 | 46 | begin 47 | (^[^ \t\*\n\|]+)|((?<=^\|)\s+[^ \t\*\n\|]+) 48 | end 49 | \s{2}|\t|$|\s+(?=\|) 50 | name 51 | keyword.control.robot 52 | 53 | 54 | scopeName 55 | text.robot 56 | uuid 57 | 816657c6-3f21-4ea2-95fc-14dfed6f76bc 58 | 59 | 60 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "commonjs", 4 | "target": "es5", 5 | "outDir": "out", 6 | "noLib": true, 7 | "sourceMap": true, 8 | "rootDir": "." 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } -------------------------------------------------------------------------------- /typings/node.d.ts: -------------------------------------------------------------------------------- 1 | /// -------------------------------------------------------------------------------- /typings/vscode-typings.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /vsc-extension-quickstart.md: -------------------------------------------------------------------------------- 1 | # Welcome to your VS Code Extension 2 | 3 | ## What's in the folder 4 | * This folder contains all of the files necessary for your extension 5 | * `package.json` - this is the manifest file in which you declare your language support and define 6 | the location of the grammar file that has been copied into you extension. 7 | * `syntaxes/robot.tmLanguage` - this is the Text mate grammar file that is used for tokenization 8 | * `robotframework.configuration.json` - this the language configuration, defining the tokens that are used for 9 | comments and brackets. 10 | 11 | ## Get up and running straight away 12 | * Make sure the language configuration settings in `robotframework.configuration.json` are accurate 13 | * press `F5` to open a new window with your extension loaded 14 | * create a new file with a file name suffix matching your language 15 | * verify that syntax highlight works and that the language configuration settings are working 16 | 17 | ## Make changes 18 | * you can relaunch the extension from the debug toolbar after making changes to the files listed above 19 | * you can also reload (`Ctrl+R` or `Cmd+R` on Mac) the VS Code window with your extension to load your changes 20 | 21 | ## Add more language features 22 | * To add features such as intellisense, hovers and validators check out the VS Code extenders documentation at 23 | https://code.visualstudio.com/docs 24 | 25 | ## Install your extension 26 | * To start using your extension with Visual Studio Code copy it into the /.vscode/extensions folder and restart Code. 27 | * To share your extension with the world, read on https://code.visualstudio.com/docs about publishing an extension. --------------------------------------------------------------------------------