c9search_highlight_rules.js 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Distributed under the BSD license:
  3. *
  4. * Copyright (c) 2010, Ajax.org B.V.
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions are met:
  9. * * Redistributions of source code must retain the above copyright
  10. * notice, this list of conditions and the following disclaimer.
  11. * * Redistributions in binary form must reproduce the above copyright
  12. * notice, this list of conditions and the following disclaimer in the
  13. * documentation and/or other materials provided with the distribution.
  14. * * Neither the name of Ajax.org B.V. nor the
  15. * names of its contributors may be used to endorse or promote products
  16. * derived from this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
  22. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  25. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. *
  29. * ***** END LICENSE BLOCK ***** */
  30. define(function(require, exports, module) {
  31. "use strict";
  32. var oop = require("../lib/oop");
  33. var lang = require("../lib/lang");
  34. var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
  35. function safeCreateRegexp(source, flag) {
  36. try {
  37. return new RegExp(source, flag);
  38. } catch(e) {}
  39. }
  40. var C9SearchHighlightRules = function() {
  41. // regexp must not have capturing parentheses. Use (?:) instead.
  42. // regexps are ordered -> the first match is used
  43. this.$rules = {
  44. "start" : [
  45. {
  46. tokenNames : ["c9searchresults.constant.numeric", "c9searchresults.text", "c9searchresults.text", "c9searchresults.keyword"],
  47. regex : "(^\\s+[0-9]+)(:\\s)(.+)",
  48. onMatch : function(val, state, stack) {
  49. var values = this.splitRegex.exec(val);
  50. var types = this.tokenNames;
  51. var tokens = [{
  52. type: types[0],
  53. value: values[1]
  54. },{
  55. type: types[1],
  56. value: values[2]
  57. }];
  58. var regex = stack[1];
  59. var str = values[3];
  60. var m;
  61. var last = 0;
  62. if (regex && regex.exec) {
  63. regex.lastIndex = 0;
  64. while (m = regex.exec(str)) {
  65. var skipped = str.substring(last, m.index);
  66. last = regex.lastIndex;
  67. if (skipped)
  68. tokens.push({type: types[2], value: skipped});
  69. if (m[0])
  70. tokens.push({type: types[3], value: m[0]});
  71. else if (!skipped)
  72. break;
  73. }
  74. }
  75. if (last < str.length)
  76. tokens.push({type: types[2], value: str.substr(last)});
  77. return tokens;
  78. }
  79. },
  80. {
  81. token : ["string", "text"], // single line
  82. regex : "(\\S.*)(:$)"
  83. },
  84. {
  85. regex : "Searching for .*$",
  86. onMatch: function(val, state, stack) {
  87. var parts = val.split("\x01");
  88. if (parts.length < 3)
  89. return "text";
  90. var options, search, replace;
  91. var i = 0;
  92. var tokens = [{
  93. value: parts[i++] + "'",
  94. type: "text"
  95. }, {
  96. value: search = parts[i++],
  97. type: "text" // "c9searchresults.keyword"
  98. }, {
  99. value: "'" + parts[i++],
  100. type: "text"
  101. }];
  102. // replaced
  103. if (parts[2] !== " in") {
  104. replace = parts[i];
  105. tokens.push({
  106. value: "'" + parts[i++] + "'",
  107. type: "text"
  108. }, {
  109. value: parts[i++],
  110. type: "text"
  111. });
  112. }
  113. // path
  114. tokens.push({
  115. value: " " + parts[i++] + " ",
  116. type: "text"
  117. });
  118. // options
  119. if (parts[i+1]) {
  120. options = parts[i+1];
  121. tokens.push({
  122. value: "(" + parts[i+1] + ")",
  123. type: "text"
  124. });
  125. i += 1;
  126. } else {
  127. i -= 1;
  128. }
  129. while (i++ < parts.length) {
  130. parts[i] && tokens.push({
  131. value: parts[i],
  132. type: "text"
  133. });
  134. }
  135. if (replace) {
  136. search = replace;
  137. options = "";
  138. }
  139. if (search) {
  140. if (!/regex/.test(options))
  141. search = lang.escapeRegExp(search);
  142. if (/whole/.test(options))
  143. search = "\\b" + search + "\\b";
  144. }
  145. var regex = search && safeCreateRegexp(
  146. "(" + search + ")",
  147. / sensitive/.test(options) ? "g" : "ig"
  148. );
  149. if (regex) {
  150. stack[0] = state;
  151. stack[1] = regex;
  152. }
  153. return tokens;
  154. }
  155. },
  156. {
  157. regex : "\\d+",
  158. token: "constant.numeric"
  159. }
  160. ]
  161. };
  162. };
  163. oop.inherits(C9SearchHighlightRules, TextHighlightRules);
  164. exports.C9SearchHighlightRules = C9SearchHighlightRules;
  165. });