PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-5-pre1/org/gjt/sp/jedit/SplitConfigParser.java

#
Java | 337 lines | 241 code | 30 blank | 66 comment | 27 complexity | 67548d10838b01e616506306dabe7ec5 MD5 | raw file
Possible License(s): BSD-3-Clause, AGPL-1.0, Apache-2.0, LGPL-2.0, LGPL-3.0, GPL-2.0, CC-BY-SA-3.0, LGPL-2.1, GPL-3.0, MPL-2.0-no-copyleft-exception, IPL-1.0
  1. /*
  2. * :tabSize=8:indentSize=8:noTabs=false:
  3. * :folding=explicit:collapseFolds=1:
  4. *
  5. * Copyright (C) 1999, 2004 Slava Pestov
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. package org.gjt.sp.jedit;
  22. import java.io.IOException;
  23. import java.io.StreamTokenizer;
  24. import java.io.StringReader;
  25. import java.util.ArrayDeque;
  26. import java.util.ArrayList;
  27. import java.util.Deque;
  28. import java.util.List;
  29. public class SplitConfigParser
  30. {
  31. //{{{ private members
  32. private String splitConfig;
  33. private boolean includeSplits = true;
  34. private boolean includeFiles = true;
  35. private boolean includeRemotes = false;
  36. //}}}
  37. //{{{ SplitConfigParser constructor
  38. /**
  39. * @param splitConfig The string to parse and adjust.
  40. */
  41. public SplitConfigParser(String splitConfig)
  42. {
  43. this.splitConfig = splitConfig == null ? "" : splitConfig;
  44. }
  45. //}}}
  46. //{{{ Setters
  47. /**
  48. * @param b If true, retain any splits in the split configuration.
  49. */
  50. public void setIncludeSplits(boolean b)
  51. {
  52. includeSplits = b;
  53. }
  54. /**
  55. * @param b If true, retain any file names found in the split configuration.
  56. */
  57. public void setIncludeFiles(boolean b)
  58. {
  59. includeFiles = b;
  60. }
  61. /**
  62. * @param b If true, and if include files is true, then retain any remote file
  63. * names found in the split configuration.
  64. */
  65. public void setIncludeRemoteFiles(boolean b)
  66. {
  67. includeRemotes = includeFiles && b;
  68. }
  69. //}}}
  70. //{{{ parse()
  71. /**
  72. * Parses the given split configuration string and removes splits, file names,
  73. * and remote file names bases on the settings for this parser.
  74. * @return The split configuration string adjusted for user preferences.
  75. */
  76. public String parse()
  77. {
  78. if (splitConfig == null || splitConfig.length() == 0)
  79. {
  80. return "";
  81. }
  82. Deque<Object> tokenStack = new ArrayDeque<Object>();
  83. Deque<Object> splitStack = new ArrayDeque<Object>();
  84. BufferSet bufferset = new BufferSet(includeFiles, includeRemotes);
  85. boolean haveSplit = false;
  86. try
  87. {
  88. StreamTokenizer st = new StreamTokenizer(new StringReader(splitConfig));
  89. st.whitespaceChars(0, ' ');
  90. st.wordChars('#', '~');
  91. st.commentChar('!');
  92. st.quoteChar('"');
  93. st.eolIsSignificant(false);
  94. int token = st.nextToken();
  95. while (token != StreamTokenizer.TT_EOF)
  96. {
  97. switch (token)
  98. {
  99. case StreamTokenizer.TT_WORD:
  100. if ("vertical".equals(st.sval) || "horizontal".equals(st.sval))
  101. {
  102. // handle split -- create new Split, populate it with
  103. // the first 2 items in the split stack.
  104. if (includeSplits)
  105. {
  106. Object right = splitStack.pop();
  107. Object left = splitStack.pop();
  108. Split split = new Split();
  109. split.setLeft(left);
  110. split.setRight(right);
  111. split.setDirection(st.sval);
  112. int offset = (Integer) tokenStack.pop();
  113. split.setOffset(offset);
  114. splitStack.push(split);
  115. haveSplit = true;
  116. }
  117. }
  118. else if ("buffer".equals(st.sval) || "buff".equals(st.sval))
  119. {
  120. // add to buffer set
  121. Object filename = tokenStack.pop();
  122. bufferset.addBuffer(filename.toString());
  123. }
  124. else if ("bufferset".equals(st.sval))
  125. {
  126. // close out current buffer set, push to split stack,
  127. // create new buffer set.
  128. Object scope = tokenStack.pop();
  129. bufferset.setScope(scope.toString());
  130. splitStack.push(bufferset);
  131. bufferset = new BufferSet(includeFiles, includeRemotes);
  132. }
  133. break;
  134. case StreamTokenizer.TT_NUMBER:
  135. tokenStack.push((int) st.nval);
  136. break;
  137. case '"':
  138. tokenStack.push(st.sval);
  139. break;
  140. }
  141. token = st.nextToken();
  142. }
  143. StringBuilder sb = new StringBuilder();
  144. // check if splitStack has any Split objects, if not, collapse all
  145. // BufferSets to a single BufferSet.
  146. if (haveSplit)
  147. {
  148. while (!splitStack.isEmpty())
  149. {
  150. sb.append(splitStack.pop().toString()).append(' ');
  151. }
  152. }
  153. else
  154. {
  155. // no splits, only buffersets
  156. BufferSet allBuffers = new BufferSet();
  157. while (!splitStack.isEmpty())
  158. {
  159. BufferSet bs = (BufferSet) splitStack.pop();
  160. if (allBuffers.getScope() == null)
  161. {
  162. allBuffers.setScope(bs.getScope());
  163. }
  164. allBuffers.addBufferSet(bs);
  165. }
  166. sb.append(allBuffers.toString());
  167. }
  168. // need the replaceAll to make sure Windows backslashes
  169. // don't get unescaped prematurely
  170. return sb.toString().replaceAll("\\\\", "\\\\\\\\").trim();
  171. }
  172. catch (IOException e)
  173. {
  174. // StringReader will not throw an IOException as long as the
  175. // string it is reading is not null, which won't happen here.
  176. }
  177. return splitConfig;
  178. }
  179. //}}}
  180. //{{{ BufferSet
  181. // Represents a set of file names for buffers.
  182. private class BufferSet
  183. {
  184. List<String> buffers = new ArrayList<String>();
  185. String scope = null;
  186. boolean includeFiles = true;
  187. boolean includeRemotes = false;
  188. public BufferSet() {}
  189. public BufferSet(boolean includeFiles, boolean includeRemotes)
  190. {
  191. this.includeFiles = includeFiles;
  192. this.includeRemotes = includeRemotes;
  193. }
  194. public void addBuffer(String s)
  195. {
  196. if (includeFiles)
  197. {
  198. if (includeRemotes)
  199. {
  200. buffers.add(s);
  201. return;
  202. }
  203. if (!isRemote(s))
  204. {
  205. buffers.add(s);
  206. }
  207. }
  208. }
  209. public List<String> getBuffers()
  210. {
  211. return buffers;
  212. }
  213. public void addBufferSet(BufferSet bs)
  214. {
  215. buffers.addAll(bs.getBuffers());
  216. }
  217. public void setScope(String s)
  218. {
  219. scope = s;
  220. }
  221. public String getScope()
  222. {
  223. return scope;
  224. }
  225. public String toString()
  226. {
  227. StringBuilder sb = new StringBuilder();
  228. if (buffers.size() == 0)
  229. {
  230. sb.append("\"Untitled-1\" buffer ");
  231. }
  232. else
  233. {
  234. for (int i = 0; i < buffers.size(); i++)
  235. {
  236. sb.append('\"').append(buffers.get(i)).append('\"');
  237. sb.append(i == 0 ? " buffer " : " buff ");
  238. }
  239. }
  240. if (scope == null)
  241. {
  242. scope = "view";
  243. }
  244. sb.append('\"').append(scope).append("\" bufferset");
  245. return sb.toString();
  246. }
  247. /**
  248. * @return true if the uri points to a file that is remote, that is, the
  249. * protocol of the give uri is something other than 'file'.
  250. */
  251. public boolean isRemote(String uri)
  252. {
  253. if (MiscUtilities.isURL(uri))
  254. {
  255. String protocol = MiscUtilities.getProtocolOfURL(uri);
  256. return !protocol.equals("file");
  257. }
  258. return false;
  259. }
  260. }
  261. //}}}
  262. //{{{ Split
  263. private class Split
  264. {
  265. Object left = null;
  266. Object right = null;
  267. String direction = null;
  268. int offset = 0;
  269. // no error checking, assumes caller will pass a BufferSet or a Split
  270. public void setLeft(Object left)
  271. {
  272. this.left = left;
  273. }
  274. // no error checking, assumes caller will pass a BufferSet or a Split
  275. public void setRight(Object right)
  276. {
  277. this.right = right;
  278. }
  279. // no error checking, assumes caller will send 'horizontal' or 'vertical'
  280. public void setDirection(String direction)
  281. {
  282. this.direction = direction;
  283. }
  284. // no error checking, assumes caller will send offset >= 0
  285. public void setOffset(int offset)
  286. {
  287. this.offset = offset;
  288. }
  289. public String toString()
  290. {
  291. StringBuilder sb = new StringBuilder();
  292. if (left != null)
  293. {
  294. sb.append(left.toString()).append(' ');
  295. }
  296. if (right != null)
  297. {
  298. sb.append(right.toString()).append(' ');
  299. }
  300. sb.append(offset).append(' ').append(direction);
  301. return sb.toString();
  302. }
  303. }
  304. //}}}
  305. }