/plugins/SideKick/tags/release-0-7-3/sidekick/SideKickParser.java

# · Java · 273 lines · 91 code · 22 blank · 160 comment · 12 complexity · c53375e1e1050f6dfd2fc4e253498cc0 MD5 · raw file

  1. /*
  2. * SideKickParser.java
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright 2003 Slava Pestov
  7. * 2005 Robert McKinnon
  8. *
  9. * This program is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU General Public License
  11. * as published by the Free Software Foundation; either version 2
  12. * of the License, or any later version.
  13. *
  14. * This program is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  17. * GNU General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22. */
  23. package sidekick;
  24. //{{{ Imports
  25. import java.util.*;
  26. import org.gjt.sp.jedit.*;
  27. import errorlist.DefaultErrorSource;
  28. import org.gjt.sp.util.Log;
  29. //}}}
  30. /**
  31. * An abstract base class for plugin-provided parser implementations.<p>
  32. *
  33. * Plugins can provide SideKick parsers by defining entries in their
  34. * <code>services.xml</code> files like so:
  35. *
  36. * <pre>&lt;SERVICE CLASS="sidekick.SideKickParser" NAME="<i>name</i>"&gt;
  37. * new <i>MyParser<i>();
  38. *&lt;/SERVICE&gt;</pre>
  39. *
  40. * See <code>org.gjt.sp.jedit.ServiceManager</code> for details.<p>
  41. *
  42. * Note that each <code>SideKickParser</code> subclass has a name which is
  43. * used to key a property <code>sidekick.parser.<i>name</i>.label</code>.<p>
  44. *
  45. * To associate a parser with some edit modes, define properties like this:
  46. * <pre>mode.scheme.sidekick.parser=lisp
  47. *mode.lisp.sidekick.parser=lisp</pre>
  48. *
  49. * @version $Id: SideKickParser.java 7616 2006-10-18 11:45:49Z hertzhaft $
  50. * @author Slava Pestov
  51. */
  52. public abstract class SideKickParser {
  53. public static final String SERVICE = "sidekick.SideKickParser";
  54. //{{{ SideKickParser constructor
  55. /**
  56. * The parser constructor.
  57. *
  58. */
  59. public SideKickParser( String serviceName ) {
  60. this.name = serviceName;
  61. } //}}}
  62. //{{{ getName() method
  63. /**
  64. * Returns the parser's name.
  65. */
  66. public final String getName() {
  67. return name;
  68. } //}}}
  69. //{{{ stop() method
  70. /**
  71. * Stops the parse request currently in progress. It is up to the
  72. * parser to implement this.
  73. * @since SideKick 0.3
  74. */
  75. public void stop() {} //}}}
  76. //{{{ activate() method
  77. /**
  78. * This method is called when a buffer using this parser is selected
  79. * in the specified view.
  80. * @param view The view
  81. * @since SideKick 0.2
  82. * @deprecated Use the form taking an <code>EditPane</code> instead.
  83. */
  84. public void activate( View view ) {} //}}}
  85. //{{{ deactivate() method
  86. /**
  87. * This method is called when a buffer using this parser is no longer
  88. * selected in the specified view.
  89. * @param view The view
  90. * @since SideKick 0.2
  91. * @deprecated Use the form taking an <code>EditPane</code> instead.
  92. */
  93. public void deactivate( View view ) {} //}}}
  94. //{{{ activate() method
  95. /**
  96. * This method is called when a buffer using this parser is selected
  97. * in the specified view.
  98. * @param editPane The edit pane
  99. * @since SideKick 0.3.1
  100. */
  101. public void activate( EditPane editPane ) {
  102. activate( editPane.getView() );
  103. Log.log( Log.DEBUG, this, getName() + ": activated for " + editPane.getBuffer() );
  104. } //}}}
  105. //{{{ deactivate() method
  106. /**
  107. * This method is called when a buffer using this parser is no longer
  108. * selected in the specified view.
  109. * @param editPane The edit pane
  110. * @since SideKick 0.3.1
  111. */
  112. public void deactivate( EditPane editPane ) {
  113. deactivate( editPane.getView() );
  114. Log.log( Log.DEBUG, this, getName() + ": deactivated" );
  115. } //}}}
  116. //{{{ parse() method
  117. /**
  118. * Parses the given text and returns a tree model.
  119. *
  120. * @param buffer The buffer to parse.
  121. * @param errorSource An error source to add errors to.
  122. *
  123. * @return A new instance of the <code>SideKickParsedData</code> class.
  124. */
  125. public abstract SideKickParsedData parse( Buffer buffer,
  126. DefaultErrorSource errorSource );
  127. //}}}
  128. //{{{ supportsCompletion() method
  129. /**
  130. * Returns if the parser supports code completion.
  131. *
  132. * Returns false by default.
  133. */
  134. public boolean supportsCompletion() {
  135. return true;
  136. } //}}}
  137. //{{{ canHandleBackspace() method
  138. /**
  139. * <p>
  140. * Returns true if the parser can handle
  141. * the backspace key being typed when
  142. * the completion popup is open,
  143. * else false if not.
  144. * </p><p>
  145. * If false, the completion popup is
  146. * closed when backspace is typed.
  147. * </p><p>
  148. * If true, the
  149. * {@link SideKickCompletion#handleKeystroke(int, char)}
  150. * method must be overidden to handle receiving
  151. * the backspace character, '\b', as a value
  152. * for the keyChar parameter.
  153. * </p><p>
  154. * Returns false by default.
  155. * </p>
  156. * @since SideKick 0.3.4
  157. */
  158. public boolean canHandleBackspace() {
  159. return false;
  160. } //}}}
  161. //{{{ canCompleteAnywhere() method
  162. /**
  163. * Returns if completion popups should be shown after any period of
  164. * inactivity. Otherwise, they are only shown if explicitly requested
  165. * by the user.
  166. *
  167. * Returns true by default.
  168. */
  169. public boolean canCompleteAnywhere() {
  170. return true;
  171. } //}}}
  172. //{{{ getInstantCompletionTriggers() method
  173. /**
  174. * Returns a list of characters which trigger completion immediately.
  175. *
  176. * Returns null by default.
  177. *
  178. */
  179. public String getInstantCompletionTriggers() {
  180. return null;
  181. } //}}}
  182. //{{{ getParseTriggers() method
  183. /**
  184. * Returns a list of characters which trigger a buffer re-parse.
  185. *
  186. * Returns null by default.
  187. * @since SideKick 0.3
  188. *
  189. */
  190. public String getParseTriggers() {
  191. return null;
  192. } //}}}
  193. //{{{ complete() method
  194. /**
  195. * Returns completions suitable for insertion at the specified position.
  196. *
  197. * Returns null by default.
  198. *
  199. * @param editPane The edit pane involved.
  200. * @param caret The caret position.
  201. */
  202. public SideKickCompletion complete( EditPane editPane, int caret ) {
  203. try {
  204. String[] keywords = editPane.getBuffer().getMode().getTokenMarker().getMainRuleSet().getKeywords().getKeywords();
  205. if (keywords.length > 0) {
  206. String word = getWordAtCaret( editPane, caret );
  207. if (word != null && word.length() > 0) {
  208. List possibles = new ArrayList();
  209. for (int i = 0; i < keywords.length; i++) {
  210. String kw = keywords[i];
  211. if (kw.startsWith(word) && !kw.equals(word)) {
  212. possibles.add(keywords[i]);
  213. }
  214. }
  215. Collections.sort(possibles);
  216. return new ConcreteSideKickCompletion(editPane.getView(), word, possibles);
  217. }
  218. }
  219. }
  220. catch ( Exception e ) {
  221. }
  222. return null;
  223. } //}}}
  224. private String getWordAtCaret( EditPane editPane, int caret ) {
  225. if ( caret <= 0 ) {
  226. return "";
  227. }
  228. Buffer buffer = editPane.getBuffer();
  229. String text = buffer.getText(0, caret);
  230. Mode mode = buffer.getMode();
  231. String word_break_chars = ( String ) mode.getProperty( "wordBreakChars" );
  232. if ( word_break_chars == null ) {
  233. word_break_chars = "";
  234. }
  235. word_break_chars += " \n\r\t";
  236. int offset = 0;
  237. for (int i = 0; i < word_break_chars.length(); i++) {
  238. int maybe = text.lastIndexOf(word_break_chars.charAt(i)) + 1;
  239. if (maybe > offset) {
  240. offset = maybe;
  241. }
  242. }
  243. return text.substring(offset);
  244. }
  245. class ConcreteSideKickCompletion extends SideKickCompletion {
  246. public ConcreteSideKickCompletion(View view, String word, List possibles) {
  247. super(view, word, possibles);
  248. }
  249. }
  250. protected String name;
  251. }