1 21 22 package org.armedbear.j; 23 24 import java.awt.event.KeyEvent ; 25 import java.util.HashMap ; 26 import java.util.StringTokenizer ; 27 import org.armedbear.lisp.Interpreter; 28 import org.armedbear.lisp.Lisp; 29 import org.armedbear.lisp.LispObject; 30 31 public class LispMode extends AbstractMode implements Constants, Mode 32 { 33 private static final LispMode mode = new LispMode(); 34 35 private LispMode() 36 { 37 super(LISP_MODE, LISP_MODE_NAME); 38 keywords = new Keywords(this); 39 setProperty(Property.INDENT_SIZE, 2); 40 setProperty(Property.HIGHLIGHT_BRACKETS, true); 41 } 42 43 protected LispMode(int id, String displayName) 44 { 45 super(id, displayName); 46 } 47 48 public static Mode getMode() 49 { 50 return mode; 51 } 52 53 public String getCommentStart() 54 { 55 return ";; "; 56 } 57 58 public final SyntaxIterator getSyntaxIterator(Position pos) 59 { 60 return new LispSyntaxIterator(pos); 61 } 62 63 public Formatter getFormatter(Buffer buffer) 64 { 65 return new LispFormatter(buffer); 66 } 67 68 protected void setKeyMapDefaults(KeyMap km) 69 { 70 km.mapKey(KeyEvent.VK_TAB, 0, "tab"); 71 km.mapKey(KeyEvent.VK_TAB, CTRL_MASK, "insertTab"); 72 km.mapKey(KeyEvent.VK_F12, 0, "wrapComment"); 73 km.mapKey(KeyEvent.VK_ENTER, 0, "newlineAndIndent"); 74 km.mapKey(KeyEvent.VK_T, CTRL_MASK, "findTag"); 75 km.mapKey(KeyEvent.VK_PERIOD, ALT_MASK, "findTagAtDot"); 76 km.mapKey(KeyEvent.VK_COMMA, ALT_MASK, "listMatchingTagsAtDot"); 77 km.mapKey(KeyEvent.VK_PERIOD, CTRL_MASK | ALT_MASK, "findTagAtDotOtherWindow"); 78 km.mapKey(')', "closeParen"); 79 km.mapKey(KeyEvent.VK_F1, ALT_MASK, "hyperspec"); 80 km.mapKey(KeyEvent.VK_F, CTRL_MASK | ALT_MASK, "forwardSexp"); 81 km.mapKey(KeyEvent.VK_B, CTRL_MASK | ALT_MASK, "backwardSexp"); 82 km.mapKey(KeyEvent.VK_D, CTRL_MASK | ALT_MASK, "downList"); 83 km.mapKey(KeyEvent.VK_U, CTRL_MASK | ALT_MASK, "backwardUpList"); 84 km.mapKey(KeyEvent.VK_X, CTRL_MASK | ALT_MASK, "evalDefunLisp"); 85 km.mapKey(KeyEvent.VK_C, CTRL_MASK | ALT_MASK, "compileDefunLisp"); 86 km.mapKey(KeyEvent.VK_R, CTRL_MASK | ALT_MASK, "evalRegionLisp"); 87 km.mapKey(KeyEvent.VK_M, CTRL_MASK, "lispFindMatchingChar"); 88 km.mapKey(KeyEvent.VK_M, CTRL_MASK | SHIFT_MASK, "lispSelectSyntax"); 89 km.mapKey(KeyEvent.VK_9, CTRL_MASK | SHIFT_MASK, "insertParentheses"); 90 km.mapKey(KeyEvent.VK_0, CTRL_MASK | SHIFT_MASK, "movePastCloseAndReindent"); 91 } 92 93 public void populateModeMenu(Editor editor, Menu menu) 94 { 95 boolean enabled = LispShell.findLisp(null) != null; 96 if (isSlimeLoaded()) { 97 menu.add(editor, "Eval Region", 'R', "(slime:slime-eval-region)", enabled); 98 menu.add(editor, "Eval Defun", 'D', "(slime:slime-eval-defun)", enabled); 99 menu.add(editor, "Compile Defun", 'C', "(slime:slime-compile-defun)", enabled); 100 menu.add(editor, "Load File", 'L', "(slime:slime-load-file)", enabled); 101 menu.add(editor, "Compile File", 'F', "(slime:slime-compile-file)", enabled); 102 menu.add(editor, "Compile and Load File", 'A', "(slime:slime-compile-and-load-file)", enabled); 103 } else { 104 menu.add(editor, "Eval Region", 'R', "evalRegionLisp", enabled); 105 menu.add(editor, "Eval Defun", 'D', "evalDefunLisp", enabled); 106 menu.add(editor, "Compile Defun", 'C', "compileDefunLisp", enabled); 107 menu.add(editor, "Load File", 'L', "loadLispFile", enabled); 108 menu.add(editor, "Compile File", 'F', "compileLispFile", enabled); 109 menu.add(editor, "Compile and Load File", 'A', "compileAndLoadLispFile", enabled); 110 } 111 } 112 113 private static final boolean isSlimeLoaded() 114 { 115 if (Editor.isLispInitialized()) { 116 try { 117 LispObject result = 118 Interpreter.evaluate("(sys:featurep :slime)"); 119 return (result != Lisp.NIL) ? true : false; 120 } 121 catch (Throwable t) { 122 Log.debug(t); 123 } 124 } 125 return false; 126 } 127 128 public boolean isTaggable() 129 { 130 return true; 131 } 132 133 public Tagger getTagger(SystemBuffer buffer) 134 { 135 return new LispTagger(buffer); 136 } 137 138 private static final String validChars = 139 "!$%&*+-./0123456789<=>?ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz{}~"; 140 141 public final boolean isIdentifierStart(char c) 142 { 143 return validChars.indexOf(c) >= 0; 144 } 145 146 public final boolean isIdentifierPart(char c) 147 { 148 return validChars.indexOf(c) >= 0; 149 } 150 151 private static final HashMap definers = new HashMap (); 152 153 static { 154 String [] strings = new String [] { 155 "defclass", "defconstant", "defgeneric", "define-condition", 156 "defmacro", "defmethod", "defparameter", "defstruct", "deftype", 157 "defun", "defvar" 158 }; 159 for (int i = strings.length; i-- > 0;) 160 definers.put(strings[i], strings[i]); 161 definers.put("def!struct", "defstruct"); 163 definers.put("defmacro-mundanely", "defmacro"); 164 definers.put("def!macro", "defmacro"); 165 definers.put("defslimefun", "defun"); 167 definers.put("definterface", "defgeneric"); 168 definers.put("defimplementation", "defmethod"); 169 } 170 171 public static final String translateDefiner(String s) 172 { 173 if (s.length() >= 5 && s.startsWith("def")) 174 return (String ) definers.get(s); 175 return null; 176 } 177 178 public boolean isInQuote(Buffer buffer, Position pos) 179 { 180 final Line line = pos.getLine(); 182 final int offset = pos.getOffset(); 183 boolean inQuote = false; 184 for (int i = 0; i < offset; i++) { 185 char c = line.charAt(i); 186 if (c == '\\') { 187 ++i; 189 } else if (inQuote) { 190 if (c == '"') 191 inQuote = false; 192 } else if (c == '"') { 193 inQuote = true; 194 } 195 } 196 return inQuote; 197 } 198 199 public boolean canIndent() 200 { 201 return true; 202 } 203 204 private final String [] specials = new String [] { 205 "block", "case", "catch", "do-all-symbols", "do-external-symbols", 206 "do-symbols", "dolist", "dotimes", "ecase", "etypecase", "eval-when", 207 "flet", "handler-bind", "labels", "lambda", "let", "let*", "locally", 208 "loop", "macrolet", "multiple-value-bind", "progn", "typecase", 209 "unless", "when" 210 }; 211 212 private final String [] elispSpecials = new String [] { 213 "while" 214 }; 215 216 private final String [] hemlockSpecials = new String [] { 217 "frob", "with-mark" 218 }; 219 220 public int getCorrectIndentation(Line line, Buffer buffer) 221 { 222 final Line model = findModel(line); 223 if (model == null) 224 return 0; 225 final int modelIndent = buffer.getIndentation(model); 226 final String modelTrim = model.trim(); 227 if (line.flags() == STATE_QUOTE) { 228 if (modelTrim.length() > 0 && modelTrim.charAt(0) == '"') 229 return modelIndent + 1; 230 else 231 return modelIndent; 232 } 233 if (modelTrim.length() == 0) 234 return 0; 235 if (modelTrim.charAt(0) == ';') 236 return modelIndent; 237 final int indentSize = buffer.getIndentSize(); 238 Position here = new Position(line, 0); 239 Position pos = findContainingSexp(here); 240 if (pos == null) return 0; 242 Debug.bugIfNot(pos.getChar() == '('); 243 int offset = pos.getOffset(); 244 if (offset > 1) { 245 if (new Position(pos.getLine(), offset - 2).lookingAt("'#(")) 246 return buffer.getCol(pos) + 1; 247 } 248 if (offset > 0) { 249 if (pos.getLine().charAt(offset-1) == '\'') 250 return buffer.getCol(pos) + 1; 251 } 252 Position posFirst = downList(pos); 253 if (posFirst != null) { 254 if (posFirst.equals(here)) 255 return buffer.getCol(pos) + 1; 256 char firstChar = posFirst.getChar(); 257 if (firstChar == '(' || firstChar == ',') { 258 return buffer.getCol(posFirst); 261 } 262 String token = gatherToken(posFirst); 264 if (token.equals("do") || token.equals("do*")) { 265 Position p1 = forwardSexp(posFirst); 267 if (p1 != null) { 268 p1.skipWhitespace(); 270 Position p2 = forwardSexp(p1); 272 if (p2 != null) { 273 p2 = forwardSexp(p2); 275 if (buffer.needsRenumbering()) 277 buffer.renumber(); 278 if (p2 != null && here.isBefore(p2)) { 279 return buffer.getCol(p1); 282 } 283 } 284 } 285 return buffer.getCol(pos) + indentSize; 286 } 287 if (token.equals("handler-case")) { 288 Position p1 = forwardSexp(posFirst); 289 if (p1 != null) { 290 p1.skipWhitespace(); 293 if (buffer.needsRenumbering()) 295 buffer.renumber(); 296 if (here.isBefore(p1)) 297 return buffer.getCol(pos) + indentSize * 2; 298 } 299 return buffer.getCol(pos) + indentSize; 300 } 301 if (token.startsWith("def") || 302 Utilities.isOneOf(token, specials) || 303 Utilities.isOneOf(token, elispSpecials) || 304 Utilities.isOneOf(token, hemlockSpecials) || 305 token.startsWith("with-")) 306 return buffer.getCol(pos) + indentSize; 307 Position posSecond = forwardSexp(posFirst); 310 if (posSecond != null) { 311 posSecond.skipWhitespace(); 312 if (posSecond.getChar() != ';') 313 if (posSecond.getLine() == pos.getLine()) 314 return buffer.getCol(posSecond); 315 } 316 } 317 return buffer.getCol(pos) + 1; 318 } 319 320 private static Line findModel(Line line) 321 { 322 Line model = line.previous(); 323 if (line.flags() == STATE_COMMENT) { 324 while (model != null && model.isBlank()) 326 model = model.previous(); 327 } else { 328 while (model != null) { 329 if (isAcceptableModel(model)) 330 break; else 332 model = model.previous(); 333 } 334 } 335 return model; 336 } 337 338 private static boolean isAcceptableModel(Line model) 339 { 340 String trim = model.trim(); 341 if (trim.length() == 0) 342 return false; 343 if (trim.charAt(0) == ';') 344 return false; 345 return true; 346 } 347 348 private String gatherToken(Position start) 349 { 350 Position pos = start.copy(); 351 FastStringBuffer sb = new FastStringBuffer(); 352 while (true) { 353 char c = pos.getChar(); 354 if (Character.isWhitespace(c)) 355 break; 356 sb.append(c); 357 if (!pos.next()) 358 break; 359 } 360 return sb.toString(); 361 } 362 363 private static Position findStartOfDefun(Position pos) 364 { 365 Line line = pos.getLine(); 366 while (true) { 367 if (line.getText().startsWith("(def")) 368 return new Position(line, 0); 369 Line prev = line.previous(); 370 if (prev == null) 371 return new Position(line, 0); 372 line = prev; 373 } 374 } 375 376 public static Position findContainingSexp(Position start) 377 { 378 LispSyntaxIterator it = new LispSyntaxIterator(start); 379 int parenCount = 0; 380 while (true) { 381 switch (it.prevChar()) { 382 case ')': 383 ++parenCount; 384 break; 385 case '(': 386 if (parenCount == 0) { 387 return it.getPosition(); 389 } 390 --parenCount; 391 break; 392 case SyntaxIterator.DONE: 393 return null; 394 default: 395 break; 396 } 397 } 398 } 399 400 private Position downList(Position start) 401 { 402 if (start == null) 403 return null; 404 Position pos = start.copy(); 405 char c; 407 while (true) { 408 pos.skipWhitespace(); 409 c = pos.getChar(); 410 if (c == ';') 411 skipComment(pos); 412 else 413 break; 414 } 415 while (true) { 417 if (c == ')') 418 return null; if (c == '(') { 420 if (!pos.next()) 422 return null; 423 while (true) { 425 pos.skipWhitespace(); 426 c = pos.getChar(); 427 if (c == ';') 428 skipComment(pos); 429 else 430 break; 431 } 432 if (pos.atEnd()) 433 return null; 434 return pos; 435 } 436 if (c == '"') { 437 skipString(pos); 439 if (pos.atEnd()) 440 return null; 441 continue; 442 } 443 if (c == ';') { 444 skipComment(pos); 445 if (pos.atEnd()) 446 return null; 447 continue; 448 } 449 if (!pos.next()) 450 return null; 451 c = pos.getChar(); 452 } 453 } 454 455 public static void downList() 456 { 457 final Editor editor = Editor.currentEditor(); 458 if (editor.getMode() instanceof LispMode) { 459 Position pos = mode.downList(editor.getDot()); 460 if (pos != null) 461 editor.moveDotTo(pos); 462 } 463 } 464 465 public static void backwardUpList() 466 { 467 final Editor editor = Editor.currentEditor(); 468 if (editor.getMode() instanceof LispMode) { 469 Position pos = findContainingSexp(editor.getDot()); 470 if (pos != null) 471 editor.moveDotTo(pos); 472 } 473 } 474 475 private void skipString(Position pos) 476 { 477 while (true) { 478 if (!pos.next()) 479 return; 480 switch (pos.getChar()) { 481 case '\\': 482 if (!pos.next()) 483 return; 484 break; 485 case '"': 486 pos.next(); 487 return; 488 } 489 } 490 } 491 492 private Position forwardSexp(Position start) 493 { 494 if (start == null) 495 return null; 496 Position pos = start.copy(); 497 char c; 499 while (true) { 500 pos.skipWhitespace(); 501 c = pos.getChar(); 502 if (c == ';') 503 skipComment(pos); 504 else 505 break; 506 } 507 if (c == ')') 509 return null; if (c == '(') { 511 int parenCount = 1; 513 while (true) { 514 if (!pos.next()) 515 return null; 516 switch (pos.getChar()) { 517 case ';': 518 skipComment(pos); 519 break; 520 case ')': 521 --parenCount; 522 if (parenCount == 0) { 523 if (pos.next()) 524 return pos; 525 else 526 return null; 527 } 528 break; 529 case '(': 530 ++parenCount; 531 break; 532 default: 533 break; 534 } 535 } 536 } 537 if (c == '"') { 538 while (true) { 539 if (!pos.next()) 540 return null; 541 switch (pos.getChar()) { 542 case '\\': 543 if (!pos.next()) 544 return null; 545 break; 546 case '"': 547 if (!pos.next()) 548 return null; 549 return pos; 550 default: 551 break; 552 } 553 } 554 } 555 while (true) { 557 if (!pos.next()) 558 return null; 559 c = pos.getChar(); 560 if (Character.isWhitespace(c) || c == '(' || c == ')') 561 return pos; 562 } 563 } 564 565 private Position backwardSexp(Position start) 566 { 567 Position pos = findContainingSexp(start); 568 if (pos == null) { 569 LispSyntaxIterator it = new LispSyntaxIterator(start); 571 while (true) { 572 char c = it.prevChar(); 573 if (c == SyntaxIterator.DONE) 574 return null; 575 if (!Character.isWhitespace(c)) { 576 pos = it.getPosition(); 577 break; 578 } 579 } 580 if (pos.getChar() == ')') 581 return findContainingSexp(pos); 582 while (true) { 583 if (!pos.prev()) 584 return pos; 585 if (Character.isWhitespace(pos.getChar())) { 586 pos.next(); 587 return pos; 588 } 589 } 590 } 591 pos = downList(pos); 592 if (pos == null) 593 return null; 594 while (true) { 595 Position last = pos; 596 pos = forwardSexp(pos); 597 if (pos == null) 598 return last; 599 char c; 601 while (true) { 602 pos.skipWhitespace(); 603 c = pos.getChar(); 604 if (c == ';') 605 skipComment(pos); 606 else 607 break; 608 } 609 if (c == ')') 610 return last; 611 if (pos.equals(start)) 612 return last; 613 if (pos.isAfter(start)) 614 return last; 615 } 616 } 617 618 private static void skipComment(Position pos) 620 { 621 Line nextLine = pos.getNextLine(); 622 if (nextLine != null) 623 pos.moveTo(nextLine, 0); 624 } 625 626 public static void forwardSexp() 627 { 628 final Editor editor = Editor.currentEditor(); 629 if (editor.getMode() instanceof LispMode) { 630 Position pos = mode.forwardSexp(editor.getDot()); 631 if (pos != null) 632 editor.moveDotTo(pos); 633 } 634 } 635 636 public static void backwardSexp() 637 { 638 final Editor editor = Editor.currentEditor(); 639 if (editor.getMode() instanceof LispMode) { 640 Position pos = mode.backwardSexp(editor.getDot()); 641 if (pos != null) 642 editor.moveDotTo(pos); 643 } 644 } 645 646 public static void lispFindMatchingChar() 647 { 648 final Editor editor = Editor.currentEditor(); 649 Position dot = editor.getDotCopy(); 650 if (dot == null) 651 return; 652 Position pos = findDelimiterNear(dot); 653 editor.setWaitCursor(); 654 Position match = editor.findMatchInternal(pos, 0); 655 editor.setDefaultCursor(); 656 if (match != null) { 657 if (match.getChar() == ')') 659 match.next(); 660 editor.addUndo(SimpleEdit.MOVE); 661 editor.unmark(); 662 editor.updateDotLine(); 663 editor.getDot().moveTo(match); 664 editor.updateDotLine(); 665 editor.moveCaretToDotCol(); 666 } else 667 editor.status("No match"); 668 } 669 670 public static void lispSelectSyntax() 671 { 672 final Editor editor = Editor.currentEditor(); 673 Position dot = editor.getDotCopy(); 674 if (dot == null) 675 return; 676 Position pos; 677 if (editor.getMark() != null) { 678 pos = findContainingSexp(dot); 679 } else { 680 pos = findDelimiterNear(dot); 681 if (pos == null) 682 pos = findContainingSexp(dot); 683 } 684 if (pos == null) 685 return; 686 editor.setWaitCursor(); 687 Position match = editor.findMatchInternal(pos, 0); 688 if (match != null) { 689 if (pos.getChar() == ')') 690 pos.next(); 691 else if (match.getChar() == ')') 692 match.next(); 693 if (pos.getLine() != match.getLine()) { 694 Region r = new Region(editor.getBuffer(), pos, match); 696 Position begin = r.getBegin(); 697 if (begin.getLine().substring(0, begin.getOffset()).trim().length() == 0) { 698 Position end = r.getEnd(); 699 String trim = end.getLine().substring(end.getOffset()).trim(); 700 if (trim.length() == 0 || trim.charAt(0) == ';') { 701 begin.setOffset(0); 703 if (end.getNextLine() != null) 704 end.moveTo(end.getNextLine(), 0); 705 else 706 end.setOffset(end.getLineLength()); 707 if (pos.isBefore(match)) { 708 pos = begin; 709 match = end; 710 } else { 711 match = begin; 712 pos = end; 713 } 714 } 715 } 716 } 717 editor.addUndo(SimpleEdit.MOVE); 718 editor.unmark(); 719 editor.getDot().moveTo(pos); 720 editor.setMarkAtDot(); 721 editor.updateDotLine(); 722 editor.getDot().moveTo(match); 723 editor.updateDotLine(); 724 editor.moveCaretToDotCol(); 725 if (editor.getDotLine() != editor.getMarkLine()) 726 editor.setUpdateFlag(REPAINT); 727 } else 728 editor.status("No match"); 729 editor.setDefaultCursor(); 730 } 731 732 private static Position findDelimiterNear(Position pos) 733 { 734 Position saved = pos.copy(); 735 if (pos.getChar() == '(') 736 return pos; 737 if (pos.getOffset() > 0) { 738 pos.prev(); 739 if (pos.getChar() == ')') 740 return pos; 741 } 742 pos.moveTo(saved); 744 while (pos.getOffset() > 0) { 745 pos.prev(); 747 char c = pos.getChar(); 748 if (c == '(' || c == ')') 749 return pos; 750 } 751 pos.moveTo(saved); 753 final int limit = pos.getLineLength() - 1; 754 while (pos.getOffset() < limit) { 755 pos.next(); 757 char c = pos.getChar(); 758 if (c == '(' || c == ')') 759 return pos; 760 if (c == ';') 761 return null; } 763 return null; 764 } 765 766 private static Editor getLispShellEditor(Editor editor) 767 { 768 Editor ed = editor.getOtherEditor(); 769 if (ed != null) { 770 Buffer b = ed.getBuffer(); 771 if (b instanceof CommandInterpreter) { 772 CommandInterpreter comint = (CommandInterpreter) b; 773 if (comint.isLisp()) 774 return ed; 775 } 776 } 777 CommandInterpreter lisp = LispShell.findLisp(null); 778 if (lisp == null) { 779 MessageDialog.showMessageDialog("No Lisp shell is running", "Error"); 780 return null; 781 } 782 ed = findEditor(lisp); 783 if (ed != null) 784 return ed; 785 return editor.displayInOtherWindow(lisp); 786 } 787 788 private static Editor findEditor(Buffer buf) 789 { 790 Editor ed = null; 791 for (EditorIterator it = new EditorIterator(); it.hasNext();) { 792 ed = it.nextEditor(); 793 if (ed.getBuffer() == buf) 794 return ed; 795 } 796 return null; 797 } 798 799 public static String getCurrentDefun(Editor editor) 800 { 801 Position begin = findStartOfDefun(editor.getDot()); 802 if (begin != null && begin.lookingAt("(def")) { 803 Position end = mode.forwardSexp(begin); 804 if (end != null) { 805 Region r = new Region(editor.getBuffer(), begin, end); 806 return r.toString().trim(); 807 } 808 } 809 return null; 810 } 811 812 private static String getDefunName(String s) 813 { 814 StringTokenizer st = new StringTokenizer (s); 815 int count = st.countTokens(); 816 if (count >= 2) { 817 st.nextToken(); 819 return st.nextToken().toUpperCase(); 821 } 822 return ""; 823 } 824 825 public static void evalDefunLisp() 826 { 827 final Editor editor = Editor.currentEditor(); 828 if (editor.getMode() != mode) 829 return; 830 Editor ed = getLispShellEditor(editor); 831 if (ed != null) { 832 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 833 String defun = getCurrentDefun(editor); 834 if (defun != null) { 835 String name = getDefunName(defun); 836 if (name != null) { 837 Position end = lisp.getEnd(); 838 end.getLine().setFlags(STATE_INPUT); 839 lisp.insertString(end, ";;; Evaluating defun " + name + " ...\n"); 840 lisp.renumber(); 841 ed.eob(); 842 ed.getDotLine().setFlags(0); 843 lisp.send(defun); 844 } 845 } 846 } 847 } 848 849 public static void compileDefunLisp() 850 { 851 final Editor editor = Editor.currentEditor(); 852 if (editor.getMode() != mode) 853 return; 854 Editor ed = getLispShellEditor(editor); 855 if (ed != null) { 856 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 857 String defun = getCurrentDefun(editor); 858 if (defun != null) { 859 String name = getDefunName(defun); 860 if (name != null) { 861 Position end = lisp.getEnd(); 862 end.getLine().setFlags(STATE_INPUT); 863 lisp.insertString(end, ";;; Compiling defun " + name + " ...\n"); 864 lisp.renumber(); 865 ed.eob(); 866 ed.getDotLine().setFlags(0); 867 lisp.send("(CL:PROGN " + defun + " (CL:COMPILE '" + name + "))\n"); 868 } 869 } 870 } 871 } 872 873 public static void evalRegionLisp() 874 { 875 final Editor editor = Editor.currentEditor(); 876 if (editor.getMode() != mode) 877 return; 878 if (editor.getMark() == null) 879 return; 880 if (editor.isColumnSelection()) { 881 editor.notSupportedForColumnSelections(); 882 return; 883 } 884 Editor ed = getLispShellEditor(editor); 885 if (ed != null) { 886 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 887 Position bufEnd = lisp.getEnd(); 888 bufEnd.getLine().setFlags(STATE_INPUT); 889 lisp.insertString(bufEnd, ";;; Evaluating region ...\n"); 890 lisp.renumber(); 891 ed.eob(); 892 ed.getDotLine().setFlags(0); 893 lisp.send(new Region(editor).toString().trim()); 894 } 895 } 896 897 public static void loadLispFile() 898 { 899 final Editor editor = Editor.currentEditor(); 900 if (editor.getMode() != mode) 901 return; 902 Editor ed = getLispShellEditor(editor); 903 if (ed != null) { 904 Buffer buffer = editor.getBuffer(); 905 boolean save = false; 906 if (buffer.isModified()) { 907 int response = 908 ConfirmDialog.showConfirmDialogWithCancelButton(editor, 909 CHECK_SAVE_PROMPT, 910 "Load File"); 911 switch (response) { 912 case RESPONSE_YES: 913 save = true; 914 break; 915 case RESPONSE_NO: 916 break; 917 case RESPONSE_CANCEL: 918 return; 919 } 920 editor.repaintNow(); 921 } 922 if (!save || buffer.save()) { 923 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 924 String path = editor.getBuffer().getFile().canonicalPath(); 925 if (path != null) { 926 Position end = lisp.getEnd(); 927 end.getLine().setFlags(STATE_INPUT); 928 lisp.insertString(end, ";;; Loading file " + path + " ...\n"); 929 lisp.renumber(); 930 ed.eob(); 931 ed.getDotLine().setFlags(0); 932 lisp.send("(CL:LOAD \"" + path + "\")\n"); 933 } 934 } 935 } 936 } 937 938 public static void compileLispFile() 939 { 940 final Editor editor = Editor.currentEditor(); 941 if (editor.getMode() != mode) 942 return; 943 Editor ed = getLispShellEditor(editor); 944 if (ed != null) { 945 Buffer buffer = editor.getBuffer(); 946 boolean save = false; 947 if (buffer.isModified()) { 948 int response = 949 ConfirmDialog.showConfirmDialogWithCancelButton(editor, 950 CHECK_SAVE_PROMPT, 951 "Compile File"); 952 switch (response) { 953 case RESPONSE_YES: 954 save = true; 955 break; 956 case RESPONSE_NO: 957 break; 958 case RESPONSE_CANCEL: 959 return; 960 } 961 editor.repaintNow(); 962 } 963 if (!save || buffer.save()) { 964 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 965 String path = editor.getBuffer().getFile().canonicalPath(); 966 if (path != null) { 967 Position end = lisp.getEnd(); 968 end.getLine().setFlags(STATE_INPUT); 969 lisp.insertString(end, ";;; Compiling " + path + " ...\n"); 970 lisp.renumber(); 971 ed.eob(); 972 ed.getDotLine().setFlags(0); 973 lisp.send("(CL:COMPILE-FILE \"" + path + "\")\n"); 974 } 975 } 976 } 977 } 978 979 public static void compileAndLoadLispFile() 980 { 981 final Editor editor = Editor.currentEditor(); 982 if (editor.getMode() != mode) 983 return; 984 Editor ed = getLispShellEditor(editor); 985 if (ed != null) { 986 Buffer buffer = editor.getBuffer(); 987 boolean save = false; 988 if (buffer.isModified()) { 989 int response = 990 ConfirmDialog.showConfirmDialogWithCancelButton(editor, 991 CHECK_SAVE_PROMPT, 992 "Compile and Load File"); 993 switch (response) { 994 case RESPONSE_YES: 995 save = true; 996 break; 997 case RESPONSE_NO: 998 break; 999 case RESPONSE_CANCEL: 1000 return; 1001 } 1002 editor.repaintNow(); 1003 } 1004 if (!save || buffer.save()) { 1005 CommandInterpreter lisp = (CommandInterpreter) ed.getBuffer(); 1006 String path = editor.getBuffer().getFile().canonicalPath(); 1007 if (path != null) { 1008 Position end = lisp.getEnd(); 1009 end.getLine().setFlags(STATE_INPUT); 1010 lisp.insertString(end, ";;; Compiling and loading " + path + " ...\n"); 1011 lisp.renumber(); 1012 ed.eob(); 1013 ed.getDotLine().setFlags(0); 1014 lisp.send("(CL:LOAD (CL:COMPILE-FILE \"" + path + "\"))\n"); 1015 } 1016 } 1017 } 1018 } 1019 1020 private static HashMap map; 1021 1022 public static void hyperspec() 1023 { 1024 hyperspec(null); 1025 } 1026 1027 public static void hyperspec(String s) 1028 { 1029 final Editor editor = Editor.currentEditor(); 1030 if (s == null) { 1031 if (editor.getDot() == null) 1032 return; 1033 char c = editor.getDotChar(); 1034 if (c == ')' || Character.isWhitespace(c)) { 1035 final Line dotLine = editor.getDotLine(); 1036 final String text = dotLine.getText(); 1037 for (int offset = editor.getDotOffset(); offset-- > 0;) { 1038 c = text.charAt(offset); 1039 if (mode.isIdentifierPart(c)) { 1040 s = mode.getIdentifier(dotLine, offset); 1041 break; 1042 } 1043 } 1044 } else 1045 s = mode.getIdentifier(editor.getDot()); 1046 if (s == null) 1047 return; 1048 } 1049 if (s.length() == 0) 1050 return; 1051 final Buffer buffer = editor.getBuffer(); 1052 String clhsRoot = buffer.getStringProperty(Property.CLHS_ROOT); 1053 File rootDir = File.getInstance(clhsRoot); 1054 if (rootDir == null || rootDir.isRemote() || !rootDir.isDirectory()) 1055 return; 1056 if (map == null) { 1057 File file = File.getInstance(rootDir, "Data/Map_Sym.txt"); 1058 if (!file.isFile()) 1059 return; 1060 SystemBuffer buf = new SystemBuffer(file); 1061 buf.load(); 1062 if (!buf.isLoaded()) 1063 return; 1064 map = new HashMap (); 1065 Line line = buf.getFirstLine(); 1066 while (true) { 1067 String key = line.trim().toLowerCase(); 1068 line = line.next(); 1069 if (line == null) 1070 break; 1071 if (line != null) { 1072 String value = line.trim(); 1073 if (key.length() > 0 && value.length() > 0) 1074 map.put(key, value); 1075 } 1076 line = line.next(); 1077 if (line == null) 1078 break; 1079 } 1080 } 1081 String filename = (String ) map.get(s.toLowerCase()); 1082 if (filename == null) { 1083 editor.status("No entry for \"" + s + '"'); 1084 return; 1085 } 1086 String rootPath = rootDir.canonicalPath(); 1087 File dataDir = File.getInstance(rootDir, "Data"); 1088 File file = File.getInstance(dataDir, filename); 1089 WebBuffer buf = null; 1090 if (buffer instanceof WebBuffer) { 1092 if (buffer.getFile().canonicalPath().startsWith(rootPath)) 1093 buf = (WebBuffer) buffer; 1094 } 1095 if (buf == null) { 1096 for (BufferIterator it = new BufferIterator(); it.hasNext();) { 1097 Buffer b = it.nextBuffer(); 1098 if (b instanceof WebBuffer) { 1099 if (b.getFile().canonicalPath().startsWith(rootPath)) { 1100 buf = (WebBuffer) b; 1101 break; 1102 } 1103 } 1104 } 1105 } 1106 if (buf != null) 1107 buf.go(file, 0, "text/html"); 1108 else { 1109 buf = WebBuffer.createWebBuffer(file, null, null); 1110 buf.setTransient(true); 1111 } 1112 if (editor.getBuffer() != buf) { 1113 Editor otherEditor = editor.getOtherEditor(); 1114 if (otherEditor != null) { 1115 buf.setUnsplitOnClose(false); 1116 otherEditor.makeNext(buf); 1117 } else 1118 editor.makeNext(buf); 1119 editor.displayInOtherWindow(buf); 1120 } 1121 } 1122} 1123 | Popular Tags |