Selaa lähdekoodia

Merge pull request #39 from zqlu/shell

Add Shell language
Alexandru Dima 7 vuotta sitten
vanhempi
commit
69230df585
6 muutettua tiedostoa jossa 517 lisäystä ja 1 poistoa
  1. 2 1
      scripts/bundle.js
  2. 1 0
      src/monaco.contribution.ts
  3. 18 0
      src/shell/shell.contribution.ts
  4. 282 0
      src/shell/shell.test.ts
  5. 213 0
      src/shell/shell.ts
  6. 1 0
      test/setup.js

+ 2 - 1
scripts/bundle.js

@@ -63,6 +63,7 @@ bundleOne('redis/redis');
 bundleOne('csp/csp');
 bundleOne('csp/csp');
 bundleOne('scheme/scheme');
 bundleOne('scheme/scheme');
 bundleOne('clojure/clojure');
 bundleOne('clojure/clojure');
+bundleOne('shell/shell');
 
 
 function bundleOne(moduleId, exclude) {
 function bundleOne(moduleId, exclude) {
 	requirejs.optimize({
 	requirejs.optimize({
@@ -74,7 +75,7 @@ function bundleOne(moduleId, exclude) {
 			'vs/basic-languages': REPO_ROOT + '/release/dev'
 			'vs/basic-languages': REPO_ROOT + '/release/dev'
 		},
 		},
 		optimize: 'none'
 		optimize: 'none'
-	}, function(buildResponse) {
+	}, function (buildResponse) {
 		const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js');
 		const filePath = path.join(REPO_ROOT, 'release/min/' + moduleId + '.js');
 		const fileContents = fs.readFileSync(filePath).toString();
 		const fileContents = fs.readFileSync(filePath).toString();
 		console.log();
 		console.log();

+ 1 - 0
src/monaco.contribution.ts

@@ -46,3 +46,4 @@ import './xml/xml.contribution';
 import './yaml/yaml.contribution';
 import './yaml/yaml.contribution';
 import './scheme/scheme.contribution';
 import './scheme/scheme.contribution';
 import './clojure/clojure.contribution';
 import './clojure/clojure.contribution';
+import './shell/shell.contribution';

+ 18 - 0
src/shell/shell.contribution.ts

@@ -0,0 +1,18 @@
+/*---------------------------------------------------------------------------------------------
+*  Copyright (c) Microsoft Corporation. All rights reserved.
+*  Licensed under the MIT License. See License.txt in the project root for license information.
+*--------------------------------------------------------------------------------------------*/
+'use strict';
+
+import { registerLanguage } from '../_.contribution';
+
+// Allow for running under nodejs/requirejs in tests
+const _monaco: typeof monaco =
+	typeof monaco === 'undefined' ? (<any>self).monaco : monaco;
+
+registerLanguage({
+	id: 'shell',
+	extensions: ['.sh', '.bash'],
+	aliases: ['Shell', 'sh'],
+	loader: () => _monaco.Promise.wrap(import('./shell')),
+});

+ 282 - 0
src/shell/shell.test.ts

@@ -0,0 +1,282 @@
+/*---------------------------------------------------------------------------------------------
+ *  Copyright (c) Microsoft Corporation. All rights reserved.
+ *  Licensed under the MIT License. See License.txt in the project root for license information.
+ *--------------------------------------------------------------------------------------------*/
+'use strict';
+
+import { testTokenization } from '../test/testRunner';
+
+testTokenization('shell', [
+	// Keywords
+	[{
+		line: 'if while',
+		tokens: [
+			{ startIndex: 0, type: 'keyword.shell' },
+			{ startIndex: 2, type: 'white.shell' },
+			{ startIndex: 3, type: 'keyword.shell' }
+		]
+	}],
+
+	// Predefined & attribute
+	[{
+		line: 'ps -aux | grep code',
+		tokens: [
+			{ startIndex: 0, type: 'type.identifier.shell' },
+			{ startIndex: 2, type: 'white.shell' },
+			{ startIndex: 3, type: 'attribute.name.shell' },
+			{ startIndex: 7, type: 'white.shell' },
+			{ startIndex: 8, type: 'delimiter.shell' },
+			{ startIndex: 9, type: 'white.shell' },
+			{ startIndex: 10, type: 'type.identifier.shell' },
+			{ startIndex: 14, type: 'white.shell' },
+			{ startIndex: 15, type: '' },
+		]
+	}],
+
+	[{
+		line: '# comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.shell' }
+		]
+	}, {
+		line: 'cd tree',
+		tokens: [
+			{ startIndex: 0, type: 'type.identifier.shell' },
+			{ startIndex: 2, type: 'white.shell' },
+			{ startIndex: 3, type: '' }
+		]
+	}],
+
+	// Shebang
+	[{
+		line: '#!/bin/env bash',
+		tokens: [
+			{ startIndex: 0, type: 'metatag.shell' }
+		]
+	}],
+
+	// Comments
+	[{
+		line: '#',
+		tokens: [
+			{ startIndex: 0, type: 'comment.shell' }
+		]
+	}],
+
+	[{
+		line: '# a comment',
+		tokens: [
+			{ startIndex: 0, type: 'comment.shell' }
+		]
+	}],
+
+	[{
+		line: '    # a comment',
+		tokens: [
+			{ startIndex: 0, type: 'white.shell' },
+			{ startIndex: 4, type: 'comment.shell' }
+		]
+	}],
+
+	// numbers
+	[{
+		line: '0',
+		tokens: [
+			{ startIndex: 0, type: 'number.shell' }
+		]
+	}],
+
+	[{
+		line: '0.0',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.shell' }
+		]
+	}],
+
+	[{
+		line: '0x123',
+		tokens: [
+			{ startIndex: 0, type: 'number.hex.shell' }
+		]
+	}],
+
+	[{
+		line: '23.5',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.shell' }
+		]
+	}],
+
+	[{
+		line: '23.5e3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.shell' }
+		]
+	}],
+
+	[{
+		line: '23.5E3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.shell' }
+		]
+	}],
+
+	[{
+		line: '1.72e-3',
+		tokens: [
+			{ startIndex: 0, type: 'number.float.shell' }
+		]
+	}],
+
+	[{
+		line: '0+0',
+		tokens: [
+			{ startIndex: 0, type: 'number.shell' },
+			{ startIndex: 1, type: 'delimiter.shell' },
+			{ startIndex: 2, type: 'number.shell' }
+		]
+	}],
+
+	[{
+		line: '100+10',
+		tokens: [
+			{ startIndex: 0, type: 'number.shell' },
+			{ startIndex: 3, type: 'delimiter.shell' },
+			{ startIndex: 4, type: 'number.shell' }
+		]
+	}],
+
+	[{
+		line: '0 + 0',
+		tokens: [
+			{ startIndex: 0, type: 'number.shell' },
+			{ startIndex: 1, type: 'white.shell' },
+			{ startIndex: 2, type: 'delimiter.shell' },
+			{ startIndex: 3, type: 'white.shell' },
+			{ startIndex: 4, type: 'number.shell' }
+		]
+	}],
+
+	// Strings
+	[{
+		line: "'test string'",
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		]
+	}],
+
+	[{
+		line: '"test string"',
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		]
+	}],
+
+	[{
+		line: "'test",
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		],
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: "string'",
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		]
+	}],
+
+	[{
+		line: '"test',
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		],
+	}, {
+		line: '',
+		tokens: [
+
+		]
+	}, {
+		line: 'string"',
+		tokens: [
+			{ startIndex: 0, type: 'string.shell' }
+		]
+	}],
+
+	// Parameters
+	[{
+		line: '$1',
+		tokens: [
+			{ startIndex: 0, type: 'variable.predefined.shell' }
+		]
+	}],
+
+	[{
+		line: '$a',
+		tokens: [
+			{ startIndex: 0, type: 'variable.shell' }
+		]
+	}],
+
+	[{
+		line: '${string:position}',
+		tokens: [
+			{ startIndex: 0, type: 'variable.shell' },
+			{ startIndex: 8, type: 'delimiter.shell' },
+			{ startIndex: 9, type: 'variable.shell' }
+		]
+	}],
+
+	[{
+		line: '$(pwd)',
+		tokens: [
+			{ startIndex: 0, type: 'variable.shell' },
+		]
+	}],
+
+	[{
+		line: 'echo $hello | less',
+		tokens: [
+			{ startIndex: 0, type: 'type.identifier.shell' },
+			{ startIndex: 4, type: 'white.shell' },
+			{ startIndex: 5, type: 'variable.shell' },
+			{ startIndex: 11, type: 'white.shell' },
+			{ startIndex: 12, type: 'delimiter.shell' },
+			{ startIndex: 13, type: 'white.shell' },
+			{ startIndex: 14, type: '' }
+		]
+	}],
+
+	// HereDoc
+	[{
+		line: '<< word',
+		tokens: [
+			{ startIndex: 0, type: 'constants.shell' },
+			{ startIndex: 2, type: 'white.shell' },
+			{ startIndex: 3, type: 'string.heredoc.shell' }
+		]
+	}],
+
+	[{
+		line: '<<- "word"',
+		tokens: [
+			{ startIndex: 0, type: 'constants.shell' },
+			{ startIndex: 3, type: 'white.shell' },
+			{ startIndex: 4, type: 'string.heredoc.delimiter.shell' },
+			{ startIndex: 5, type: 'string.heredoc.shell' },
+			{ startIndex: 9, type: 'string.heredoc.delimiter.shell' },
+		]
+	}],
+
+	[{
+		line: '<<< word',
+		tokens: [
+			{ startIndex: 0, type: 'constants.shell' },
+			{ startIndex: 3, type: 'white.shell' },
+			{ startIndex: 4, type: 'string.heredoc.shell' }
+		]
+	}],
+])

+ 213 - 0
src/shell/shell.ts

@@ -0,0 +1,213 @@
+/*---------------------------------------------------------------------------------------------
+*  Copyright (c) Microsoft Corporation. All rights reserved.
+*  Licensed under the MIT License. See License.txt in the project root for license information.
+*--------------------------------------------------------------------------------------------*/
+
+'use strict';
+
+import IRichLanguageConfiguration = monaco.languages.LanguageConfiguration;
+import ILanguage = monaco.languages.IMonarchLanguage;
+
+export const conf: IRichLanguageConfiguration = {
+	comments: {
+		lineComment: '#',
+	},
+	brackets: [['{', '}'], ['[', ']'], ['(', ')']],
+	autoClosingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: "'", close: "'" },
+		{ open: '`', close: '`' },
+	],
+	surroundingPairs: [
+		{ open: '{', close: '}' },
+		{ open: '[', close: ']' },
+		{ open: '(', close: ')' },
+		{ open: '"', close: '"' },
+		{ open: "'", close: "'" },
+		{ open: '`', close: '`' },
+	],
+};
+
+export const language = <ILanguage>{
+	defaultToken: '',
+	ignoreCase: true,
+	tokenPostfix: '.shell',
+
+	brackets: [
+		{ token: 'delimiter.bracket', open: '{', close: '}' },
+		{ token: 'delimiter.parenthesis', open: '(', close: ')' },
+		{ token: 'delimiter.square', open: '[', close: ']' },
+	],
+
+	keywords: [
+		'if',
+		'then',
+		'do',
+		'else',
+		'elif',
+		'while',
+		'until',
+		'for',
+		'in',
+		'esac',
+		'fi',
+		'fin',
+		'fil',
+		'done',
+		'exit',
+		'set',
+		'unset',
+		'export',
+		'function',
+	],
+
+	builtins: [
+		'ab',
+		'awk',
+		'bash',
+		'beep',
+		'cat',
+		'cc',
+		'cd',
+		'chown',
+		'chmod',
+		'chroot',
+		'clear',
+		'cp',
+		'curl',
+		'cut',
+		'diff',
+		'echo',
+		'find',
+		'gawk',
+		'gcc',
+		'get',
+		'git',
+		'grep',
+		'hg',
+		'kill',
+		'killall',
+		'ln',
+		'ls',
+		'make',
+		'mkdir',
+		'openssl',
+		'mv',
+		'nc',
+		'node',
+		'npm',
+		'ping',
+		'ps',
+		'restart',
+		'rm',
+		'rmdir',
+		'sed',
+		'service',
+		'sh',
+		'shopt',
+		'shred',
+		'source',
+		'sort',
+		'sleep',
+		'ssh',
+		'start',
+		'stop',
+		'su',
+		'sudo',
+		'svn',
+		'tee',
+		'telnet',
+		'top',
+		'touch',
+		'vi',
+		'vim',
+		'wall',
+		'wc',
+		'wget',
+		'who',
+		'write',
+		'yes',
+		'zsh',
+	],
+
+	// we include these common regular expressions
+	symbols: /[=><!~?&|+\-*\/\^;\.,]+/,
+
+	// The main tokenizer for our languages
+	tokenizer: {
+		root: [
+			{ include: '@whitespace' },
+
+			[
+				/[a-zA-Z]\w*/,
+				{
+					cases: {
+						'@keywords': 'keyword',
+						'@builtins': 'type.identifier',
+						'@default': ''
+					},
+				},
+			],
+
+			{ include: '@strings' },
+			{ include: '@parameters' },
+			{ include: '@heredoc' },
+
+			[/[{}\[\]()]/, '@brackets'],
+
+			[/-+\w+/, 'attribute.name'],
+
+			[/@symbols/, 'delimiter'],
+
+			{ include: '@numbers' },
+
+			[/[,;]/, 'delimiter'],
+		],
+
+		whitespace: [
+			[/\s+/, 'white'],
+			[/(^#!.*$)/, 'metatag'],
+			[/(^#.*$)/, 'comment'],
+		],
+
+		numbers: [
+			[/\d*\.\d+([eE][\-+]?\d+)?/, 'number.float'],
+			[/0[xX][0-9a-fA-F_]*[0-9a-fA-F]/, 'number.hex'],
+			[/\d+/, 'number'],
+		],
+
+		// Recognize strings, including those broken across lines
+		strings: [
+			[/'/, 'string', '@stringBody'],
+			[/"/, 'string', '@dblStringBody']
+		],
+		stringBody: [
+			[/'/, 'string', '@popall'],
+			[/./, 'string'],
+		],
+		dblStringBody: [
+			[/"/, 'string', '@popall'],
+			[/./, 'string'],
+		],
+
+		heredoc: [
+			[/(<<[-<]?)(\s*)(['"`]?)([\w\-]+)(['"`]?)/, ['constants', 'white', 'string.heredoc.delimiter', 'string.heredoc', 'string.heredoc.delimiter']]
+		],
+
+		parameters: [
+			[/\$\d+/, 'variable.predefined'],
+			[/\$\w+/, 'variable'],
+			[/\$[*@#?\-$!0_]/, 'variable'],
+			[/\$['"{(]/, 'variable', '@parameterBody']
+		],
+
+		parameterBody: [
+			[/[#:%*@\-!_]/, 'delimiter'],
+			[/['"{(]/, 'variable', '@pop'],
+			[/./, 'variable']
+		],
+	}
+};

+ 1 - 0
test/setup.js

@@ -67,6 +67,7 @@ define(['require'], function (require) {
 			'release/dev/st/st.test',
 			'release/dev/st/st.test',
 			'release/dev/scheme/scheme.test',
 			'release/dev/scheme/scheme.test',
 			'release/dev/clojure/clojure.test',
 			'release/dev/clojure/clojure.test',
+			'release/dev/shell/shell.test'
 		], function () {
 		], function () {
 			run(); // We can launch the tests!
 			run(); // We can launch the tests!
 		}, function (err) {
 		}, function (err) {