1 21 22 package org.armedbear.j; 23 24 import java.io.BufferedReader ; 25 import java.io.BufferedWriter ; 26 import java.io.IOException ; 27 import java.io.InputStreamReader ; 28 import java.io.OutputStreamWriter ; 29 import java.io.Writer ; 30 import java.util.Comparator ; 31 import java.util.Collections ; 32 import java.util.List ; 33 import org.armedbear.lisp.Closure; 34 import org.armedbear.lisp.LispObject; 35 36 public final class Help 37 { 38 public static final void help() 39 { 40 help(null); 41 } 42 43 public static void help(String arg) 44 { 45 final Editor editor = Editor.currentEditor(); 46 final Frame frame = editor.getFrame(); 47 final File dir = getDocumentationDirectory(); 48 if (dir == null) 49 return; 50 frame.setWaitCursor(); 51 try { 52 String fileName = "contents.html"; 53 String ref = null; 54 if (arg == null || arg.length() == 0) 55 ; 56 else if (arg.endsWith(".html")) { 57 File file = File.getInstance(dir, arg); 58 if (file != null && file.isFile()) 59 fileName = arg; 60 } else { 61 Command command = CommandTable.getCommand(arg); 62 if (command != null) { 63 fileName = "commands.html"; 64 ref = command.getName(); 65 } else { 66 Property property = Property.findProperty(arg); 67 if (property != null) { 68 fileName = "preferences.html"; 69 ref = property.getDisplayName(); 70 } 71 } 72 } 73 File file = File.getInstance(dir, fileName); 74 if (file == null || !file.isFile()) 75 return; 76 Buffer buf = null; 77 if (isHelpBuffer(editor.getBuffer())) 79 buf = editor.getBuffer(); 80 else { 81 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 82 Buffer b = it.nextBuffer(); 83 if (isHelpBuffer(b)) { 84 buf = b; 85 break; 86 } 87 } 88 } 89 if (buf != null) { 90 int offset = 0; 93 if (editor.getBuffer() == buf) { 94 offset = buf.getAbsoluteOffset(editor.getDot()); 95 } else { 96 View view = buf.getLastView(); 97 if (view != null) { 98 Position dot = view.getDot(); 99 if (dot != null) 100 offset = buf.getAbsoluteOffset(dot); 101 } 102 } 103 ((WebBuffer)buf).saveHistory(buf.getFile(), offset, 104 ((WebBuffer)buf).getContentType()); 105 if (!buf.getFile().equals(file)) { 106 ((WebBuffer)buf).go(file, 0, null); 108 } 109 Position pos = ((WebBuffer) buf).findRef(ref); 110 if (editor.getBuffer() == buf) { 111 if (pos != null) 112 editor.moveDotTo(pos); 113 } else { 114 editor.makeNext(buf); 115 Editor ed = editor.activateInOtherWindow(buf); 116 if (pos != null) { 117 ed.moveDotTo(pos); 118 ed.updateDisplay(); 119 } 120 } 121 } else { 122 buf = WebBuffer.createWebBuffer(file, null, ref); 123 Editor otherEditor = editor.getOtherEditor(); 124 if (otherEditor != null) { 125 buf.setUnsplitOnClose(otherEditor.getBuffer().unsplitOnClose()); 126 otherEditor.makeNext(buf); 127 } else { 128 buf.setUnsplitOnClose(true); 129 editor.makeNext(buf); 130 } 131 Editor ed = editor.activateInOtherWindow(buf); 132 ed.updateDisplay(); 133 } 134 } 135 finally { 136 frame.setDefaultCursor(); 137 } 138 } 139 140 private static boolean isHelpBuffer(Buffer buffer) 141 { 142 if (!(buffer instanceof WebBuffer)) 143 return false; 144 File file = buffer.getFile(); 145 if (file != null) { 146 File dir = file.getParentFile(); 147 if (dir != null && dir.equals(getDocumentationDirectory())) 148 return true; 149 } 150 return false; 151 } 152 153 public static final File getBindingsFile() 154 { 155 return File.getInstance(Directories.getTempDirectory(), "bindings.html"); 156 } 157 158 public static void listBindings() 159 { 160 final Editor editor = Editor.currentEditor(); 161 final Frame frame = editor.getFrame(); 162 frame.setWaitCursor(); 163 try { 164 File file = getBindingsFile(); 165 BufferedWriter writer = 166 new BufferedWriter (new OutputStreamWriter (file.getOutputStream())); 167 writer.write("<html>\n<head>\n<title>Keyboard Bindings</title>\n</head>\n<body>\n"); 168 File docDir = getDocumentationDirectory(); 169 writer.write("<b>"); 170 writer.write("Local Bindings ("); 171 writer.write(editor.getMode().toString()); 172 writer.write(" mode)"); 173 writer.write("</b><br><br>"); 174 addBindingsFromKeyMap(editor.getBuffer().getKeyMapForMode(), docDir, 175 writer); 176 writer.write("<br>"); 177 writer.write("<b>"); 178 writer.write("Global Bindings"); 179 writer.write("</b><br><br>"); 180 addBindingsFromKeyMap(KeyMap.getGlobalKeyMap(), docDir, writer); 181 writer.write("</body>\n</html>\n"); 182 writer.flush(); 183 writer.close(); 184 if (isListBindingsBuffer(editor.getBuffer())) { 185 ((WebBuffer)editor.getBuffer()).go(file, 0, "text/html"); 186 } else { 187 Buffer buf = null; 188 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 189 Buffer b = it.nextBuffer(); 190 if (isListBindingsBuffer(b)) { 191 buf = b; 192 break; 193 } 194 } 195 if (buf != null) 196 ((WebBuffer)buf).go(file, 0, "text/html"); 197 else 198 buf = WebBuffer.createWebBuffer(file, null, null); 199 Editor otherEditor = editor.getOtherEditor(); 200 if (otherEditor != null) { 201 buf.setUnsplitOnClose(otherEditor.getBuffer().unsplitOnClose()); 202 otherEditor.makeNext(buf); 203 } else { 204 buf.setUnsplitOnClose(true); 205 editor.makeNext(buf); 206 } 207 editor.activateInOtherWindow(buf); 208 } 209 } 210 catch (IOException e) { 211 Log.error(e); 212 } 213 finally { 214 frame.setDefaultCursor(); 215 } 216 } 217 218 private static void addBindingsFromKeyMap(KeyMap keyMap, File docDir, 219 Writer writer) 220 throws IOException 221 { 222 KeyMapping[] mappings = keyMap.getMappings(); 223 int count = mappings.length; 224 if (count == 0) { 225 writer.write("[None]<br>\n"); 226 return; 227 } 228 for (int i = 0; i < count; i++) { 229 KeyMapping mapping = mappings[i]; 230 FastStringBuffer sb = new FastStringBuffer(64); 231 sb.append(mapping.getKeyText()); 232 Object command = mapping.getCommand(); 233 if (command instanceof String ) { 234 String commandString = (String ) command; 235 int spaces = 32 - sb.length(); 236 for (int j = spaces; j-- > 0;) 237 sb.append(" "); 238 if (docDir != null) { 239 sb.append("<a HREF=\""); 240 sb.append(docDir.canonicalPath()); 241 sb.append(LocalFile.getSeparatorChar()); 242 sb.append("commands.html#"); 243 sb.append(commandString); 244 sb.append("\">"); 245 sb.append(commandString); 246 sb.append("</a>"); 247 } else 248 sb.append(commandString); 249 sb.append("<br>\n"); 250 } else if (command instanceof LispObject) { 251 int spaces = 32 - sb.length(); 252 for (int j = spaces; j-- > 0;) 253 sb.append(" "); 254 String name = ((LispObject)command).getName(); 255 if (name != null) { 256 sb.append(name); 257 } else if (command instanceof Closure) { 258 sb.append("#<CLOSURE "); 259 sb.append("@ "); 260 sb.append(Integer.toHexString(command.hashCode())); 261 sb.append(">"); 262 } 263 sb.append("<br>\n"); 264 } 265 writer.write(sb.toString()); 266 } 267 } 268 269 private static boolean isListBindingsBuffer(Buffer buffer) 270 { 271 if (!(buffer instanceof WebBuffer)) 272 return false; 273 return buffer.getFile().equals(getBindingsFile()); 274 } 275 276 public static void apropos() 277 { 278 final Editor editor = Editor.currentEditor(); 279 InputDialog d = new InputDialog(editor, "Apropos:", "Apropos", null); 280 d.setHistory(new History("apropos")); 281 editor.centerDialog(d); 282 d.show(); 283 String arg = d.getInput(); 284 if (arg == null) 285 return; 286 arg = arg.trim(); 287 if (arg.length() == 0) 288 return; 289 apropos(arg); 290 } 291 292 public static void apropos(String arg) 293 { 294 final File dir = getDocumentationDirectory(); 295 if (dir == null) 296 return; 297 final Editor editor = Editor.currentEditor(); 298 final Frame frame = editor.getFrame(); 299 frame.setWaitCursor(); 300 try { 301 File file = getAproposFile(); 302 BufferedWriter writer = 303 new BufferedWriter (new OutputStreamWriter (file.getOutputStream())); 304 writer.write("<html>\n<head>\n<title>"); 305 writer.write("Apropos "); 306 writer.write('"'); 307 writer.write(arg); 308 writer.write('"'); 309 writer.write("</title>\n</head>\n<body>\n"); 310 writer.write("<b>"); 311 writer.write("Commands"); 312 writer.write("</b><br><br>"); 313 File helpFile = File.getInstance(dir, "commands.html"); 314 if (helpFile != null && !helpFile.isFile()) 315 helpFile = null; 316 List commands = CommandTable.apropos(arg); 317 sort(commands); 318 addAproposEntries(commands, helpFile, writer); 319 writer.write("<br>"); 320 writer.write("<b>"); 321 writer.write("Preferences"); 322 writer.write("</b><br><br>"); 323 helpFile = File.getInstance(dir, "preferences.html"); 324 if (helpFile != null && !helpFile.isFile()) 325 helpFile = null; 326 List properties = Property.apropos(arg); 327 sort(properties); 328 addAproposEntries(properties, helpFile, writer); 329 writer.write("</body>\n</html>\n"); 330 writer.flush(); 331 writer.close(); 332 Editor ed; 333 if (isAproposBuffer(editor.getBuffer())) { 334 ((WebBuffer)editor.getBuffer()).go(file, 0, "text/html"); 335 ed = editor; 336 } else { 337 Buffer buf = null; 338 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 339 Buffer b = it.nextBuffer(); 340 if (isAproposBuffer(b)) { 341 buf = b; 342 break; 343 } 344 } 345 if (buf != null) 346 ((WebBuffer)buf).go(file, 0, "text/html"); 347 else { 348 buf = WebBuffer.createWebBuffer(file, null, null); 349 buf.setTransient(true); 350 } 351 Editor otherEditor = editor.getOtherEditor(); 352 if (otherEditor != null) { 353 buf.setUnsplitOnClose(otherEditor.getBuffer().unsplitOnClose()); 354 otherEditor.makeNext(buf); 355 } else { 356 buf.setUnsplitOnClose(true); 357 editor.makeNext(buf); 358 } 359 ed = editor.activateInOtherWindow(buf); 360 } 361 for (Line line = ed.getBuffer().getFirstLine(); line != null; line = line.next()) { 362 if (WebBuffer.findLink(line, 0) != null) { 363 int offset = 0; 364 while (offset < line.length()) { 365 char c = line.charAt(offset); 366 if (!Character.isWhitespace(c) && c != 160) 367 break; 368 ++offset; 369 } 370 ed.moveDotTo(line, offset); 371 ed.updateDisplay(); 372 break; 373 } 374 } 375 } 376 catch (IOException e) { 377 Log.error(e); 378 } 379 finally { 380 frame.setDefaultCursor(); 381 } 382 } 383 384 private static Comparator comparator; 385 386 private static void sort(List list) 387 { 388 if (comparator == null) { 389 comparator = new Comparator () { 390 public int compare(Object o1, Object o2) 391 { 392 return o1.toString().compareToIgnoreCase(o2.toString()); 393 } 394 }; 395 } 396 Collections.sort(list, comparator); 397 } 398 399 private static void addAproposEntries(List list, File helpFile, 400 Writer writer) throws IOException 401 { 402 int size = 0; 403 if (list != null) 404 size = list.size(); 405 if (size > 0) { 406 for (int i = 0; i < size; i++) { 407 String s = (String ) list.get(i); 408 if (helpFile != null) { 409 writer.write(" <a HREF=\""); 410 writer.write(helpFile.canonicalPath()); 411 writer.write('#'); 412 writer.write(s); 413 writer.write("\">"); 414 } 415 writer.write(s); 416 if (helpFile != null) 417 writer.write("</a>"); 418 writer.write("<br>\n"); 419 } 420 } else 421 writer.write(" <i>None</i><br>\n"); 422 } 423 424 private static boolean isAproposBuffer(Buffer buffer) 425 { 426 if (!(buffer instanceof WebBuffer)) 427 return false; 428 return buffer.getFile().equals(getAproposFile()); 429 } 430 431 private static final File getAproposFile() 432 { 433 return File.getInstance(Directories.getTempDirectory(), "apropos.html"); 434 } 435 436 public static File getDocumentationDirectory() 437 { 438 String s = Editor.preferences().getStringProperty(Property.DOC_PATH); 439 if (s != null) { 440 Path path = new Path(s); 441 String [] array = path.list(); 442 if (array != null) { 443 for (int i = 0; i < array.length; i++) { 444 File dir = File.getInstance(array[i]); 445 if (isDocDir(dir)) 446 return dir; 447 } 448 } 449 } 450 s = System.getProperty("java.class.path"); 451 if (s != null) { 452 final File userDir = 453 File.getInstance(System.getProperty("user.dir")); 454 Path path = new Path(s); 455 String [] array = path.list(); 456 if (array != null) { 457 for (int i = 0; i < array.length; i++) { 458 String filename = array[i]; 459 if (filename.toLowerCase().endsWith("j.jar")) { 460 File jarFile = File.getInstance(userDir, filename); 461 if (jarFile != null && jarFile.isFile()) { 462 File jarDir = jarFile.getParentFile(); 463 if (jarDir != null && jarDir.isDirectory()) { 464 File docDir = File.getInstance(jarDir, "doc"); 465 if (isDocDir(docDir)) 466 return docDir; 467 } 468 } 469 } else if (filename.toLowerCase().endsWith("src")) { 470 File srcDir = File.getInstance(userDir, filename); 472 if (srcDir != null && srcDir.isDirectory()) { 473 File parentDir = srcDir.getParentFile(); if (parentDir != null && parentDir.isDirectory()) { 475 File docDir = File.getInstance(parentDir, "doc"); if (isDocDir(docDir)) 477 return docDir; 478 } 479 } 480 } else { 481 String suffix = LocalFile.getSeparator() + "j" + LocalFile.getSeparator() + "j.jar"; 482 if (filename.endsWith(suffix)) { 483 File dataDir = File.getInstance(filename.substring(0, filename.length() - suffix.length())); File docDir = File.getInstance(dataDir, "doc" + LocalFile.getSeparator() + "j"); if (isDocDir(docDir)) 487 return docDir; 488 } 489 } 490 } 491 } 492 } 493 if (Platform.isPlatformUnix()) { 495 File dir = File.getInstance("/usr/local/share/doc/j"); 496 if (isDocDir(dir)) 497 return dir; 498 dir = File.getInstance("/usr/share/doc/j"); 499 if (isDocDir(dir)) 500 return dir; 501 } else if (Platform.isPlatformWindows()) { 502 String dirname = cygpath("/usr/local/share/doc/j"); 503 if (dirname != null) { 504 File dir = File.getInstance(dirname); 505 if (isDocDir(dir)) 506 return dir; 507 } 508 } 509 return null; 510 } 511 512 private static String cygpath(String s) 513 { 514 String [] cmdarray = {"cygpath", "-w", s}; 515 try { 516 Process process = Runtime.getRuntime().exec(cmdarray); 517 BufferedReader reader = new BufferedReader (new InputStreamReader (process.getInputStream())); 518 return reader.readLine(); 519 } 520 catch (Throwable t) { 521 return null; 522 } 523 } 524 525 private static boolean isDocDir(File dir) 527 { 528 if (dir == null ||!dir.isDirectory()) 529 return false; 530 File check = File.getInstance(dir, "commands.html"); 531 if (check == null || !check.isFile()) 532 return false; 533 return true; 534 } 535 } 536 | Popular Tags |