PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/jEdit/tags/jedit-4-2-pre14/org/gjt/sp/jedit/help/HelpIndex.java

#
Java | 396 lines | 281 code | 44 blank | 71 comment | 43 complexity | d2cf4e531bdf7771f57df4607aedd00b 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. * HelpIndex.java - Index for help searching feature
  3. * :tabSize=8:indentSize=8:noTabs=false:
  4. * :folding=explicit:collapseFolds=1:
  5. *
  6. * Copyright (C) 2002 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.help;
  23. //{{{ Imports
  24. import java.io.*;
  25. import java.net.*;
  26. import java.util.zip.*;
  27. import java.util.*;
  28. import org.gjt.sp.jedit.io.*;
  29. import org.gjt.sp.jedit.*;
  30. import org.gjt.sp.util.Log;
  31. //}}}
  32. class HelpIndex
  33. {
  34. //{{{ HelpIndex constructor
  35. public HelpIndex()
  36. {
  37. words = new HashMap();
  38. files = new ArrayList();
  39. ignoreWord("a");
  40. ignoreWord("an");
  41. ignoreWord("and");
  42. ignoreWord("are");
  43. ignoreWord("as");
  44. ignoreWord("be");
  45. ignoreWord("by");
  46. ignoreWord("can");
  47. ignoreWord("do");
  48. ignoreWord("for");
  49. ignoreWord("from");
  50. ignoreWord("how");
  51. ignoreWord("i");
  52. ignoreWord("if");
  53. ignoreWord("in");
  54. ignoreWord("is");
  55. ignoreWord("it");
  56. ignoreWord("not");
  57. ignoreWord("of");
  58. ignoreWord("on");
  59. ignoreWord("or");
  60. ignoreWord("s");
  61. ignoreWord("that");
  62. ignoreWord("the");
  63. ignoreWord("this");
  64. ignoreWord("to");
  65. ignoreWord("will");
  66. ignoreWord("with");
  67. ignoreWord("you");
  68. } //}}}
  69. /* //{{{ HelpIndex constructor
  70. public HelpIndex(String fileListPath, String wordIndexPath)
  71. {
  72. this();
  73. } //}}} */
  74. //{{{ indexEditorHelp() method
  75. /**
  76. * Indexes all available help, including the jEdit user's guide, FAQ,]
  77. * and plugin documentation.
  78. */
  79. public void indexEditorHelp()
  80. {
  81. try
  82. {
  83. String jEditHome = jEdit.getJEditHome();
  84. if(jEditHome != null)
  85. {
  86. indexDirectory(MiscUtilities.constructPath(jEditHome,"doc","users-guide"));
  87. indexDirectory(MiscUtilities.constructPath(jEditHome,"doc","FAQ"));
  88. indexDirectory(MiscUtilities.constructPath(jEditHome,"doc","news42"));
  89. }
  90. }
  91. catch(Throwable e)
  92. {
  93. Log.log(Log.ERROR,this,"Error indexing editor help");
  94. Log.log(Log.ERROR,this,e);
  95. }
  96. PluginJAR[] jars = jEdit.getPluginJARs();
  97. for(int i = 0; i < jars.length; i++)
  98. {
  99. try
  100. {
  101. indexJAR(jars[i].getZipFile());
  102. }
  103. catch(Throwable e)
  104. {
  105. Log.log(Log.ERROR,this,"Error indexing JAR: "
  106. + jars[i].getPath());
  107. Log.log(Log.ERROR,this,e);
  108. }
  109. }
  110. Log.log(Log.DEBUG,this,"Indexed " + words.size() + " words");
  111. } //}}}
  112. //{{{ indexDirectory() method
  113. /**
  114. * Indexes all HTML and text files in the specified directory.
  115. * @param dir The directory
  116. */
  117. public void indexDirectory(String dir) throws Exception
  118. {
  119. String[] files = VFSManager.getFileVFS()
  120. ._listDirectory(null,dir,"*.{html,txt}",true,null);
  121. for(int i = 0; i < files.length; i++)
  122. {
  123. indexURL(files[i]);
  124. }
  125. } //}}}
  126. //{{{ indexJAR() method
  127. /**
  128. * Indexes all HTML and text files in the specified JAR file.
  129. * @param jar The JAR file
  130. */
  131. public void indexJAR(ZipFile jar) throws Exception
  132. {
  133. Enumeration e = jar.entries();
  134. while(e.hasMoreElements())
  135. {
  136. ZipEntry entry = (ZipEntry)e.nextElement();
  137. String name = entry.getName();
  138. String lname = name.toLowerCase();
  139. if(lname.endsWith(".html")/* || lname.endsWith(".txt") */)
  140. {
  141. // only works for jEdit plugins
  142. String url = "jeditresource:/" +
  143. MiscUtilities.getFileName(jar.getName())
  144. + "!/" + name;
  145. Log.log(Log.DEBUG,this,url);
  146. indexStream(jar.getInputStream(entry),url);
  147. }
  148. }
  149. } //}}}
  150. //{{{ indexURL() method
  151. /**
  152. * Reads the specified HTML file and adds all words defined therein to the
  153. * index.
  154. * @param url The HTML file's URL
  155. */
  156. public void indexURL(String url) throws Exception
  157. {
  158. InputStream _in;
  159. if(MiscUtilities.isURL(url))
  160. _in = new URL(url).openStream();
  161. else
  162. {
  163. _in = new FileInputStream(url);
  164. // hack since HelpViewer needs a URL...
  165. url = "file:" + url;
  166. }
  167. indexStream(_in,url);
  168. } //}}}
  169. //{{{ lookupWord() method
  170. public Word lookupWord(String word)
  171. {
  172. Object o = words.get(word);
  173. if(o == IGNORE)
  174. return null;
  175. else
  176. return (Word)o;
  177. } //}}}
  178. //{{{ getFile() method
  179. public HelpFile getFile(int index)
  180. {
  181. return (HelpFile)files.get(index);
  182. } //}}}
  183. //{{{ Private members
  184. private static Word.Occurrence[] EMPTY_ARRAY = new Word.Occurrence[0];
  185. // used to mark words to ignore (see constructor for the list)
  186. private static Object IGNORE = new Object();
  187. private HashMap words;
  188. private ArrayList files;
  189. //{{{ ignoreWord() method
  190. private void ignoreWord(String word)
  191. {
  192. words.put(word,IGNORE);
  193. } //}}}
  194. //{{{ indexStream() method
  195. /**
  196. * Reads the specified HTML file and adds all words defined therein to the
  197. * index.
  198. * @param _in The input stream
  199. * @param file The file
  200. */
  201. private void indexStream(InputStream _in, String fileName)
  202. throws Exception
  203. {
  204. HelpFile file = new HelpFile(fileName);
  205. files.add(file);
  206. int index = files.size() - 1;
  207. StringBuffer titleText = new StringBuffer();
  208. BufferedReader in = new BufferedReader(
  209. new InputStreamReader(_in));
  210. try
  211. {
  212. StringBuffer word = new StringBuffer();
  213. boolean insideTag = false;
  214. boolean insideEntity = false;
  215. boolean title = false;
  216. int c;
  217. while((c = in.read()) != -1)
  218. {
  219. char ch = (char)c;
  220. if(insideTag)
  221. {
  222. if(ch == '>')
  223. {
  224. if(word.toString().equals("title"))
  225. title = true;
  226. insideTag = false;
  227. word.setLength(0);
  228. }
  229. else
  230. word.append(ch);
  231. }
  232. else if(insideEntity)
  233. {
  234. if(ch == ';')
  235. insideEntity = false;
  236. }
  237. else if(ch == '<')
  238. {
  239. if(title)
  240. title = false;
  241. if(word.length() != 0)
  242. {
  243. addWord(word.toString(),index,title);
  244. word.setLength(0);
  245. }
  246. insideTag = true;
  247. }
  248. else if(ch == '&')
  249. insideEntity = true;
  250. else if(title)
  251. titleText.append(ch);
  252. else if(!Character.isLetterOrDigit(ch))
  253. {
  254. if(word.length() != 0)
  255. {
  256. addWord(word.toString(),index,title);
  257. word.setLength(0);
  258. }
  259. }
  260. else
  261. word.append(ch);
  262. }
  263. }
  264. finally
  265. {
  266. in.close();
  267. }
  268. if(titleText.length() == 0)
  269. file.title = fileName;
  270. else
  271. file.title = titleText.toString();
  272. } //}}}
  273. //{{{ addWord() method
  274. private void addWord(String word, int file, boolean title)
  275. {
  276. word = word.toLowerCase();
  277. Object o = words.get(word);
  278. if(o == IGNORE)
  279. return;
  280. if(o == null)
  281. words.put(word,new Word(word,file,title));
  282. else
  283. ((Word)o).addOccurrence(file,title);
  284. } //}}}
  285. //}}}
  286. //{{{ Word class
  287. static class Word
  288. {
  289. // how much an occurrence in the title is worth
  290. static final int TITLE_OCCUR = 10;
  291. // the word
  292. String word;
  293. // files it occurs in
  294. int occurCount = 0;
  295. Occurrence[] occurrences;
  296. Word(String word, int file, boolean title)
  297. {
  298. this.word = word;
  299. occurrences = new Occurrence[5];
  300. addOccurrence(file,title);
  301. }
  302. void addOccurrence(int file, boolean title)
  303. {
  304. for(int i = 0; i < occurCount; i++)
  305. {
  306. if(occurrences[i].file == file)
  307. {
  308. occurrences[i].count += (title ? TITLE_OCCUR : 1);
  309. return;
  310. }
  311. }
  312. if(occurCount >= occurrences.length)
  313. {
  314. Occurrence[] newOccur = new Occurrence[occurrences.length * 2];
  315. System.arraycopy(occurrences,0,newOccur,0,occurCount);
  316. occurrences = newOccur;
  317. }
  318. occurrences[occurCount++] = new Occurrence(file,title);
  319. }
  320. static class Occurrence
  321. {
  322. int file;
  323. int count;
  324. Occurrence(int file, boolean title)
  325. {
  326. this.file = file;
  327. this.count = (title ? TITLE_OCCUR : 1);
  328. }
  329. }
  330. } //}}}
  331. //{{{ HelpFile class
  332. static class HelpFile
  333. {
  334. String file;
  335. String title;
  336. HelpFile(String file)
  337. {
  338. this.file = file;
  339. }
  340. public String toString()
  341. {
  342. return title;
  343. }
  344. public boolean equals(Object o)
  345. {
  346. if(o instanceof HelpFile)
  347. return ((HelpFile)o).file.equals(file);
  348. else
  349. return false;
  350. }
  351. } //}}}
  352. }