shell.js 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. (function(mod) {
  2. if (typeof exports == "object" && typeof module == "object") // CommonJS
  3. mod(require("../../lib/codemirror"));
  4. else if (typeof define == "function" && define.amd) // AMD
  5. define(["../../lib/codemirror"], mod);
  6. else // Plain browser env
  7. mod(CodeMirror);
  8. })(function(CodeMirror) {
  9. "use strict";
  10. CodeMirror.defineMode('shell', function() {
  11. var words = {};
  12. function define(style, string) {
  13. var split = string.split(' ');
  14. for(var i = 0; i < split.length; i++) {
  15. words[split[i]] = style;
  16. }
  17. };
  18. // Atoms
  19. define('atom', 'true false');
  20. // Keywords
  21. define('keyword', 'if then do else elif while until for in esac fi fin ' +
  22. 'fil done exit set unset export function');
  23. // Commands
  24. define('builtin', 'ab awk bash beep cat cc cd chown chmod chroot clear cp ' +
  25. 'curl cut diff echo find gawk gcc get git grep kill killall ln ls make ' +
  26. 'mkdir openssl mv nc node npm ping ps restart rm rmdir sed service sh ' +
  27. 'shopt shred source sort sleep ssh start stop su sudo tee telnet top ' +
  28. 'touch vi vim wall wc wget who write yes zsh');
  29. function tokenBase(stream, state) {
  30. var sol = stream.sol();
  31. var ch = stream.next();
  32. if (ch === '\'' || ch === '"' || ch === '`') {
  33. state.tokens.unshift(tokenString(ch));
  34. return tokenize(stream, state);
  35. }
  36. if (ch === '#') {
  37. if (sol && stream.eat('!')) {
  38. stream.skipToEnd();
  39. return 'meta'; // 'comment'?
  40. }
  41. stream.skipToEnd();
  42. return 'comment';
  43. }
  44. if (ch === '$') {
  45. state.tokens.unshift(tokenDollar);
  46. return tokenize(stream, state);
  47. }
  48. if (ch === '+' || ch === '=') {
  49. return 'operator';
  50. }
  51. if (ch === '-') {
  52. stream.eat('-');
  53. stream.eatWhile(/\w/);
  54. return 'attribute';
  55. }
  56. if (/\d/.test(ch)) {
  57. stream.eatWhile(/\d/);
  58. if(!/\w/.test(stream.peek())) {
  59. return 'number';
  60. }
  61. }
  62. stream.eatWhile(/[\w-]/);
  63. var cur = stream.current();
  64. if (stream.peek() === '=' && /\w+/.test(cur)) return 'def';
  65. return words.hasOwnProperty(cur) ? words[cur] : null;
  66. }
  67. function tokenString(quote) {
  68. return function(stream, state) {
  69. var next, end = false, escaped = false;
  70. while ((next = stream.next()) != null) {
  71. if (next === quote && !escaped) {
  72. end = true;
  73. break;
  74. }
  75. if (next === '$' && !escaped && quote !== '\'') {
  76. escaped = true;
  77. stream.backUp(1);
  78. state.tokens.unshift(tokenDollar);
  79. break;
  80. }
  81. escaped = !escaped && next === '\\';
  82. }
  83. if (end || !escaped) {
  84. state.tokens.shift();
  85. }
  86. return (quote === '`' || quote === ')' ? 'quote' : 'string');
  87. };
  88. };
  89. var tokenDollar = function(stream, state) {
  90. if (state.tokens.length > 1) stream.eat('$');
  91. var ch = stream.next(), hungry = /\w/;
  92. if (ch === '{') hungry = /[^}]/;
  93. if (ch === '(') {
  94. state.tokens[0] = tokenString(')');
  95. return tokenize(stream, state);
  96. }
  97. if (!/\d/.test(ch)) {
  98. stream.eatWhile(hungry);
  99. stream.eat('}');
  100. }
  101. state.tokens.shift();
  102. return 'def';
  103. };
  104. function tokenize(stream, state) {
  105. return (state.tokens[0] || tokenBase) (stream, state);
  106. };
  107. return {
  108. startState: function() {return {tokens:[]};},
  109. token: function(stream, state) {
  110. if (stream.eatSpace()) return null;
  111. return tokenize(stream, state);
  112. }
  113. };
  114. });
  115. CodeMirror.defineMIME('text/x-sh', 'shell');
  116. });