/jEdit/tags/jedit-4-1-pre1/org/gjt/sp/jedit/search/RESearchMatcher.java

#
Java | 179 lines | 92 code | 18 blank | 69 comment | 24 complexity | 95cf81d7ed08890c376b083b880958e5 MD5 | raw file

✨ Summary
  1. /*
  2. * RESearchMatcher.java - Regular expression matcher
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 1999, 2000, 2001 Slava Pestov
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  21. */
  22. package org.gjt.sp.jedit.search;
  23. //{{{ Imports
  24. import bsh.BshMethod;
  25. import bsh.NameSpace;
  26. import gnu.regexp.*;
  27. import javax.swing.text.Segment;
  28. import org.gjt.sp.jedit.BeanShell;
  29. import org.gjt.sp.jedit.MiscUtilities;
  30. //}}}
  31. /**
  32. * A regular expression string matcher.
  33. * @author Slava Pestov
  34. * @version $Id: RESearchMatcher.java 4228 2002-06-02 06:07:31Z spestov $
  35. */
  36. public class RESearchMatcher implements SearchMatcher
  37. {
  38. /**
  39. * Perl5 syntax with character classes enabled.
  40. * @since jEdit 3.0pre5
  41. */
  42. public static final RESyntax RE_SYNTAX_JEDIT
  43. = new RESyntax(RESyntax.RE_SYNTAX_PERL5)
  44. .set(RESyntax.RE_CHAR_CLASSES)
  45. .setLineSeparator("\n");
  46. //{{{ RESearchMatcher constructor
  47. /**
  48. * Creates a new regular expression string matcher.
  49. */
  50. public RESearchMatcher(String search, String replace,
  51. boolean ignoreCase, boolean beanshell,
  52. BshMethod replaceMethod) throws Exception
  53. {
  54. if(beanshell && replaceMethod != null && replace.length() != 0)
  55. {
  56. this.beanshell = true;
  57. this.replaceMethod = replaceMethod;
  58. replaceNS = new NameSpace(BeanShell.getNameSpace(),
  59. "search and replace");
  60. }
  61. else
  62. {
  63. // gnu.regexp doesn't seem to support \n and \t in the replace
  64. // string, so implement it here
  65. this.replace = MiscUtilities.escapesToChars(replace);
  66. }
  67. re = new RE(search,(ignoreCase ? RE.REG_ICASE : 0)
  68. | RE.REG_MULTILINE,RE_SYNTAX_JEDIT);
  69. returnValue = new int[2];
  70. } //}}}
  71. //{{{ nextMatch() method
  72. /**
  73. * Returns the offset of the first match of the specified text
  74. * within this matcher.
  75. * @param text The text to search in
  76. * @param start True if the start of the segment is the beginning of the
  77. * buffer
  78. * @param end True if the end of the segment is the end of the buffer
  79. * @param firstTime If false and the search string matched at the start
  80. * offset with length zero, automatically find next match
  81. * @return an array where the first element is the start offset
  82. * of the match, and the second element is the end offset of
  83. * the match
  84. * @since jEdit 4.0pre7
  85. */
  86. public int[] nextMatch(CharIndexed text, boolean start, boolean end,
  87. boolean firstTime)
  88. {
  89. int flags = 0;
  90. // unless we are matching from the start of the buffer,
  91. // ^ should not match on the beginning of the substring
  92. if(!start)
  93. flags |= RE.REG_NOTBOL;
  94. // unless we are matching to the end of the buffer,
  95. // $ should not match on the end of the substring
  96. if(!end)
  97. flags |= RE.REG_NOTEOL;
  98. REMatch match = re.getMatch(text,0,flags);
  99. if(match == null)
  100. return null;
  101. int _start = match.getStartIndex();
  102. int _end = match.getEndIndex();
  103. // some regexps (eg ^ by itself) have a length == 0, so we
  104. // implement this hack. if you don't understand what's going on
  105. // here, then go back to watching MTV
  106. if(!firstTime && _start == 0 && _end == 0)
  107. {
  108. text.move(1);
  109. if(text.charAt(0) == CharIndexed.OUT_OF_BOUNDS)
  110. {
  111. // never mind
  112. return null;
  113. }
  114. match = re.getMatch(text,0,flags | RE.REG_NOTBOL);
  115. if(match == null)
  116. return null;
  117. else
  118. {
  119. _start = match.getStartIndex() + 1;
  120. _end = match.getEndIndex() + 1;
  121. }
  122. }
  123. returnValue[0] = _start;
  124. returnValue[1] = _end;
  125. return returnValue;
  126. } //}}}
  127. //{{{ substitute() method
  128. /**
  129. * Returns the specified text, with any substitution specified
  130. * within this matcher performed.
  131. * @param text The text
  132. */
  133. public String substitute(String text) throws Exception
  134. {
  135. REMatch match = re.getMatch(text);
  136. if(match == null)
  137. return null;
  138. if(beanshell)
  139. {
  140. int count = re.getNumSubs();
  141. for(int i = 0; i <= count; i++)
  142. replaceNS.setVariable("_" + i,match.toString(i));
  143. Object obj = BeanShell.runCachedBlock(replaceMethod,
  144. null,replaceNS);
  145. if(obj == null)
  146. return "";
  147. else
  148. return obj.toString();
  149. }
  150. else
  151. return match.substituteInto(replace);
  152. } //}}}
  153. //{{{ Private members
  154. private String replace;
  155. private RE re;
  156. private boolean beanshell;
  157. private BshMethod replaceMethod;
  158. private NameSpace replaceNS;
  159. private int[] returnValue;
  160. //}}}
  161. }