shell.js 3.1 KB

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