1 21 22 package org.armedbear.j; 23 24 import gnu.regexp.REException; 25 import java.util.Iterator ; 26 import javax.swing.SwingUtilities ; 27 import javax.swing.undo.CompoundEdit ; 28 import org.armedbear.lisp.AbstractString; 29 import org.armedbear.lisp.ConditionThrowable; 30 import org.armedbear.lisp.Fixnum; 31 import org.armedbear.lisp.Function; 32 import org.armedbear.lisp.GenericFunction; 33 import org.armedbear.lisp.JavaObject; 34 import org.armedbear.lisp.Keyword; 35 import org.armedbear.lisp.Lisp; 36 import org.armedbear.lisp.LispCharacter; 37 import org.armedbear.lisp.LispError; 38 import org.armedbear.lisp.LispObject; 39 import org.armedbear.lisp.LispThread; 40 import org.armedbear.lisp.Package; 41 import org.armedbear.lisp.Packages; 42 import org.armedbear.lisp.Pathname; 43 import org.armedbear.lisp.Primitive0; 44 import org.armedbear.lisp.Primitive1; 45 import org.armedbear.lisp.Primitive2; 46 import org.armedbear.lisp.Primitive3; 47 import org.armedbear.lisp.Primitive; 48 import org.armedbear.lisp.Primitives; 49 import org.armedbear.lisp.SimpleString; 50 import org.armedbear.lisp.Symbol; 51 import org.armedbear.lisp.TypeError; 52 import org.armedbear.lisp.UndefinedFunction; 53 import org.armedbear.lisp.WrongNumberOfArgumentsException; 54 55 public final class LispAPI extends Lisp 56 { 57 private static final Preferences preferences = Editor.preferences(); 58 59 public static final Package PACKAGE_J = 60 Packages.createPackage("J"); 61 public static final Package PACKAGE_J_INTERNALS = 62 Packages.createPackage("J-INTERNALS"); 63 static { 64 PACKAGE_J.usePackage(PACKAGE_CL); 65 PACKAGE_J.usePackage(PACKAGE_EXT); 66 PACKAGE_J.usePackage(PACKAGE_JAVA); 67 PACKAGE_J_INTERNALS.usePackage(PACKAGE_CL); 68 PACKAGE_J_INTERNALS.usePackage(PACKAGE_EXT); 69 PACKAGE_J_INTERNALS.usePackage(PACKAGE_JAVA); 70 } 71 72 public static final Symbol BUFFER_STREAM = 73 LispAPI.PACKAGE_J.addExternalSymbol("BUFFER-STREAM"); 74 75 public static final Symbol _CURRENT_COMMAND_ = 76 exportSpecial("*CURRENT-COMMAND*", PACKAGE_J, NIL); 77 78 public static final Symbol _LAST_COMMAND_ = 79 exportSpecial("*LAST-COMMAND*", PACKAGE_J, NIL); 80 81 public static final void eventHandled() 82 { 83 _LAST_COMMAND_.setSymbolValue(_CURRENT_COMMAND_.getSymbolValue()); 84 _CURRENT_COMMAND_.setSymbolValue(NIL); 85 } 86 87 public static final Editor checkEditor(LispObject obj) 88 throws ConditionThrowable 89 { 90 if (obj == null) 91 throw new NullPointerException (); 92 try { 93 return (Editor) ((JavaObject)obj).getObject(); 94 } 95 catch (ClassCastException e) { 96 signal(new TypeError("The value " + obj.writeToString() + 97 " is not an editor.")); 98 return null; 100 } 101 } 102 103 public static final Buffer checkBuffer(LispObject obj) 104 throws ConditionThrowable 105 { 106 if (obj == null) 107 throw new NullPointerException (); 108 if (obj == NIL) 109 return Editor.currentEditor().getBuffer(); 110 try { 111 return (Buffer) ((JavaObject)obj).getObject(); 112 } 113 catch (ClassCastException e) { 114 signal(new TypeError("The value " + obj.writeToString() + 115 " is not a buffer.")); 116 return null; 118 } 119 } 120 121 private static final Position checkMark(LispObject obj) 122 throws ConditionThrowable 123 { 124 if (obj == null) 125 throw new NullPointerException (); 126 try { 127 return (Position) ((JavaObject)obj).getObject(); 128 } 129 catch (ClassCastException e) { 130 signal(new TypeError("The value " + obj.writeToString() + 131 " is not a mark.")); 132 return null; 134 } 135 } 136 137 public static final Line checkLine(LispObject obj) 138 throws ConditionThrowable 139 { 140 if (obj == null) 141 throw new NullPointerException (); 142 try { 143 return (Line) ((JavaObject)obj).getObject(); 144 } 145 catch (ClassCastException e) { 146 signal(new TypeError("The value " + obj.writeToString() + 147 " is not a line.")); 148 return null; 150 } 151 } 152 153 private static final Primitive0 CURRENT_EDITOR = 155 new Primitive0("current-editor", PACKAGE_J, true, 156 "()", 157 "Returns the current editor as a Lisp object.") 158 { 159 public LispObject execute() 160 { 161 return new JavaObject(Editor.currentEditor()); 162 } 163 }; 164 165 private static final Primitive1 _SET_CURRENT_EDITOR = 167 new Primitive1("%set-current-editor", PACKAGE_J, false, 168 "(EDITOR)", 169 "Makes EDITOR the current editor.") 170 { 171 public LispObject execute(LispObject arg) throws ConditionThrowable 172 { 173 Editor.setCurrentEditor(checkEditor(arg)); 174 return arg; 175 } 176 }; 177 178 private static final Primitive0 OTHER_EDITOR = 180 new Primitive0("other-editor", PACKAGE_J, true) { 181 public LispObject execute() 182 { 183 Editor otherEditor = Editor.currentEditor().getOtherEditor(); 184 return otherEditor != null ? new JavaObject(otherEditor) : NIL; 185 } 186 }; 187 188 private static final Primitive0 CURRENT_BUFFER = 190 new Primitive0("current-buffer", PACKAGE_J, true) { 191 public LispObject execute() 192 { 193 return new JavaObject(Editor.currentEditor().getBuffer()); 194 } 195 }; 196 197 private static final Primitive1 BUFFER = 199 new Primitive1("editor-buffer", PACKAGE_J, true) 200 { 201 public LispObject execute(LispObject arg) throws ConditionThrowable 202 { 203 return new JavaObject(checkEditor(arg).getBuffer()); 204 } 205 }; 206 207 private static final Primitive BUFFER_NAME = 209 new Primitive("buffer-name", PACKAGE_J, true, "&optional buffer") 210 { 211 public LispObject execute() 212 { 213 String name = Editor.currentEditor().getBuffer().getTitle(); 214 return name != null ? new SimpleString(name) : NIL; 215 } 216 217 public LispObject execute(LispObject arg) throws ConditionThrowable 218 { 219 String name = checkBuffer(arg).getTitle(); 220 return name != null ? new SimpleString(name) : NIL; 221 } 222 }; 223 224 private static final Primitive1 GET_BUFFER = 226 new Primitive1("get-buffer", PACKAGE_J, true, "name") 227 { 228 public LispObject execute(LispObject arg) throws ConditionThrowable 229 { 230 if (arg instanceof AbstractString) { 231 String name = arg.getStringValue(); 232 BufferIterator iterator = new BufferIterator(); 233 while (iterator.hasNext()) { 234 Buffer buffer = iterator.nextBuffer(); 235 if (buffer.getTitle().equals(name)) 236 return new JavaObject(buffer); 237 } 238 return NIL; 239 } 240 if (arg instanceof JavaObject) { 241 if (((JavaObject)arg).getObject() instanceof Buffer) 242 return arg; 243 } 244 return NIL; 245 } 246 }; 247 248 private static final Primitive1 BUFFER_LIVE_P = 250 new Primitive1("buffer-live-p", PACKAGE_J, true, "object") 251 { 252 public LispObject execute(LispObject arg) throws ConditionThrowable 253 { 254 if (arg instanceof JavaObject) { 255 if (((JavaObject)arg).getObject() instanceof Buffer) { 256 if (Editor.getBufferList().contains((Buffer)((JavaObject)arg).getObject())) 257 return T; 258 } 259 } 260 return NIL; 261 } 262 }; 263 264 private static final Primitive BUFFER_PATHNAME = 266 new Primitive("buffer-pathname", PACKAGE_J, true, "&optional buffer") 267 { 268 public LispObject execute() throws ConditionThrowable 269 { 270 File file = Editor.currentEditor().getBuffer().getFile(); 271 if (file != null && file.isLocal()) { 272 String s = file.canonicalPath(); 273 if (file.isDirectory()) 274 if (!s.endsWith(LocalFile.getSeparator())) 275 s = s.concat(LocalFile.getSeparator()); 276 return new Pathname(s); 277 } 278 return NIL; 279 } 280 281 public LispObject execute(LispObject arg) throws ConditionThrowable 282 { 283 File file = checkBuffer(arg).getFile(); 284 if (file != null && file.isLocal()) { 285 String s = file.canonicalPath(); 286 if (file.isDirectory()) 287 if (!s.endsWith(LocalFile.getSeparator())) 288 s = s.concat(LocalFile.getSeparator()); 289 return new Pathname(s); 290 } 291 return NIL; 292 } 293 }; 294 295 private static final Primitive BUFFER_STRING = 297 new Primitive("buffer-string", PACKAGE_J, true, "&optional buffer") 298 { 299 public LispObject execute() throws ConditionThrowable 300 { 301 return new SimpleString(Editor.currentBuffer().getText()); 302 } 303 public LispObject execute(LispObject arg) throws ConditionThrowable 304 { 305 return new SimpleString(checkBuffer(arg).getText()); 306 } 307 }; 308 309 private static final Primitive BUFFER_SUBSTRING = 311 new Primitive("buffer-substring", PACKAGE_J, true, 312 "start end &optional buffer") 313 { 314 public LispObject execute(LispObject first, LispObject second) 315 throws ConditionThrowable 316 { 317 Region region = new Region(Editor.currentEditor().getBuffer(), 318 checkMark(first), 319 checkMark(second)); 320 return new SimpleString(region.toString()); 321 } 322 public LispObject execute(LispObject first, LispObject second, 323 LispObject third) 324 throws ConditionThrowable 325 { 326 Position start = checkMark(first); 327 Position end = checkMark(second); 328 Region region = new Region(checkBuffer(third), start, end); 329 return new SimpleString(region.toString()); 330 } 331 }; 332 333 private static final Primitive GOTO_CHAR = 336 new Primitive("goto-char", PACKAGE_J, true) 337 { 338 public LispObject execute(LispObject arg) throws ConditionThrowable 339 { 340 final Editor editor = Editor.currentEditor(); 342 if (arg instanceof Fixnum) { 343 Position pos = 344 editor.getBuffer().getPosition(((Fixnum)arg).value); 345 if (pos != null) 346 editor.moveDotTo(pos); 347 } else 348 editor.moveDotTo(checkMark(arg)); 349 return new JavaObject(editor.getDot()); 350 } 351 }; 352 353 private static final Primitive MOVE_TO_POSITION = 355 new Primitive("move-to-position", PACKAGE_J, true, 356 "mark charpos &optional line") 357 { 358 public LispObject execute(LispObject mark, LispObject charpos) 359 throws ConditionThrowable 360 { 361 Position pos = checkMark(mark); 362 pos.setOffset(Fixnum.getValue(charpos)); 363 return mark; 364 } 365 public LispObject execute(LispObject mark, LispObject charpos, 366 LispObject line) 367 throws ConditionThrowable 368 { 369 Position pos = checkMark(mark); 370 if (line == NIL) 371 pos.setOffset(Fixnum.getValue(charpos)); 372 else 373 pos.moveTo(checkLine(line), Fixnum.getValue(charpos)); 374 return mark; 375 } 376 }; 377 378 private static final Primitive0 CURRENT_POINT = 380 new Primitive0("current-point", PACKAGE_J, true, "") 381 { 382 public LispObject execute() 383 { 384 Position dot = Editor.currentEditor().getDot(); 385 if (dot != null) 386 return new JavaObject(dot.copy()); 387 return NIL; 388 } 389 }; 390 391 private static final Primitive0 CURRENT_MARK = 393 new Primitive0("current-mark", PACKAGE_J, true, "") 394 { 395 public LispObject execute() 396 { 397 Position mark = Editor.currentEditor().getMark(); 398 if (mark != null) 399 return new JavaObject(mark.copy()); 400 return NIL; 401 } 402 }; 403 404 private static final Primitive0 POINT_MIN = 406 new Primitive0("point-min", PACKAGE_J, true) 407 { 408 public LispObject execute() 409 { 410 final Line line = Editor.currentBuffer().getFirstLine(); 411 if (line == null) 412 return NIL; 413 return new JavaObject(new Position(line, 0)); 414 } 415 }; 416 417 private static final Primitive0 POINT_MAX = 419 new Primitive0("point-max", PACKAGE_J, true) 420 { 421 public LispObject execute() 422 { 423 Position pos = Editor.currentBuffer().getEnd(); 424 if (pos == null) 425 return NIL; 426 return new JavaObject(pos); 427 } 428 }; 429 430 private static final Primitive1 MAKE_MARK = 432 new Primitive1("make-mark", PACKAGE_J, true) 433 { 434 public LispObject execute(LispObject first, LispObject second) 435 throws ConditionThrowable 436 { 437 Line line = checkLine(first); 438 int offset = Fixnum.getValue(second); 439 return new JavaObject(new Position(line, offset)); 440 } 441 }; 442 443 private static final Primitive1 MARK_LINE = 445 new Primitive1("mark-line", PACKAGE_J, true) 446 { 447 public LispObject execute(LispObject arg) throws ConditionThrowable 448 { 449 return new JavaObject(checkMark(arg).getLine()); 450 } 451 }; 452 453 private static final Primitive1 MARK_CHARPOS = 455 new Primitive1("mark-charpos", PACKAGE_J, true) 456 { 457 public LispObject execute(LispObject arg) throws ConditionThrowable 458 { 459 return number(checkMark(arg).getOffset()); 460 } 461 }; 462 463 private static final Primitive0 CURRENT_LINE = 465 new Primitive0("current-line", PACKAGE_J, true) 466 { 467 public LispObject execute() 468 { 469 Editor editor = Editor.currentEditor(); 470 Position dot = Editor.currentEditor().getDot(); 471 if (dot != null) 472 return new JavaObject(dot.getLine()); 473 return NIL; 474 } 475 }; 476 477 private static final Primitive1 LINE_NEXT = 479 new Primitive1("line-next", PACKAGE_J, true) 480 { 481 public LispObject execute(LispObject arg) throws ConditionThrowable 482 { 483 Line next = checkLine(arg).next(); 484 return next != null ? new JavaObject(next) : NIL; 485 } 486 }; 487 488 private static final Primitive1 LINE_PREVIOUS = 490 new Primitive1("line-previous", PACKAGE_J, true) 491 { 492 public LispObject execute(LispObject arg) throws ConditionThrowable 493 { 494 Line prev = checkLine(arg).previous(); 495 return prev != null ? new JavaObject(prev) : NIL; 496 } 497 }; 498 499 private static final Primitive1 LINE_CHARS = 501 new Primitive1("line-chars", PACKAGE_J, true) 502 { 503 public LispObject execute(LispObject arg) throws ConditionThrowable 504 { 505 String s = checkLine(arg).getText(); 506 return s != null ? new SimpleString(s) : NIL; 507 } 508 }; 509 510 private static final Primitive1 LINE_FLAGS = 512 new Primitive1("line-flags", PACKAGE_J, true) 513 { 514 public LispObject execute(LispObject arg) throws ConditionThrowable 515 { 516 return number(checkLine(arg).flags()); 517 } 518 }; 519 520 private static final Primitive2 _SET_LINE_FLAGS = 522 new Primitive2("%set-line-flags", PACKAGE_J, false) 523 { 524 public LispObject execute(LispObject first, LispObject second) 525 throws ConditionThrowable 526 { 527 Line line = checkLine(first); 528 int flags = Fixnum.getValue(second); 529 line.setFlags(flags); 530 return second; 531 } 532 }; 533 534 private static final Primitive1 LINE_NUMBER = 536 new Primitive1("line-number", PACKAGE_J, true, "line") 537 { 538 public LispObject execute(LispObject arg) throws ConditionThrowable 539 { 540 return number(checkLine(arg).lineNumber()); 541 } 542 }; 543 544 private static final Primitive1 CHAR_AFTER = 547 new Primitive1("char-after", PACKAGE_J, true) 548 { 549 public LispObject execute(LispObject arg) throws ConditionThrowable 550 { 551 return LispCharacter.getInstance(checkMark(arg).getChar()); 552 } 553 }; 554 555 private static final Primitive1 CHAR_BEFORE = 558 new Primitive1("char-before", PACKAGE_J, true) 559 { 560 public LispObject execute(LispObject arg) throws ConditionThrowable 561 { 562 Position pos = checkMark(arg).copy(); 563 return pos.prev() ? LispCharacter.getInstance(pos.getChar()) : NIL; 564 } 565 }; 566 567 private static final Primitive FORWARD_CHAR = 570 new Primitive("forward-char", PACKAGE_J, true) 571 { 572 public LispObject execute() throws ConditionThrowable 573 { 574 return forwardChar(1); 575 } 576 public LispObject execute(LispObject arg) throws ConditionThrowable 577 { 578 return forwardChar(Fixnum.getValue(arg)); 579 } 580 }; 581 582 private static final Primitive BACKWARD_CHAR = 585 new Primitive("backward-char", PACKAGE_J, true) { 586 public LispObject execute() throws ConditionThrowable 587 { 588 return forwardChar(-1); 589 } 590 public LispObject execute(LispObject arg) throws ConditionThrowable 591 { 592 return forwardChar(-Fixnum.getValue(arg)); 593 } 594 }; 595 596 private static final LispObject forwardChar(int n) throws ConditionThrowable 597 { 598 if (n != 0) { 599 final Editor editor = Editor.currentEditor(); 600 Position pos = editor.getDot(); 601 if (pos != null) { 602 editor.addUndo(SimpleEdit.MOVE); 603 if (n > 0) { 604 while (n-- > 0) { 605 if (!pos.next()) 606 return signal(new LispError("reached end of buffer")); 607 } 608 } else { 609 Debug.assertTrue(n < 0); 610 while (n++ < 0) { 611 if (!pos.prev()) 612 return signal(new LispError("reached beginning of buffer")); 613 } 614 } 615 editor.moveCaretToDotCol(); 616 } 617 } 618 return NIL; 619 } 620 621 private static final Primitive BEGINNING_OF_LINE = 623 new Primitive("beginning-of-line", PACKAGE_J, true) 624 { 625 public LispObject execute() throws ConditionThrowable 626 { 627 Editor.currentEditor().bol(); 628 return NIL; 629 } 630 631 public LispObject execute(LispObject arg) throws ConditionThrowable 632 { 633 int n = (arg != NIL) ? Fixnum.getValue(arg) : 1; 634 final Editor editor = Editor.currentEditor(); 635 Position pos = editor.getDot(); 636 if (pos != null) { 637 editor.addUndo(SimpleEdit.MOVE); 638 while (--n > 0) { 639 Line nextLine = pos.getNextLine(); 640 if (nextLine != null) 641 pos.setLine(nextLine); 642 else 643 break; 644 } 645 pos.setOffset(0); 646 editor.moveCaretToDotCol(); 647 } 648 return NIL; 649 } 650 }; 651 652 private static final Primitive END_OF_LINE = 654 new Primitive("end-of-line", PACKAGE_J, true) 655 { 656 public LispObject execute() throws ConditionThrowable 657 { 658 Editor.currentEditor().eol(); 659 return NIL; 660 } 661 662 public LispObject execute(LispObject arg) throws ConditionThrowable 663 { 664 int n = (arg != NIL) ? Fixnum.getValue(arg) : 1; 665 final Editor editor = Editor.currentEditor(); 666 Position pos = editor.getDot(); 667 if (pos != null) { 668 editor.addUndo(SimpleEdit.MOVE); 669 while (--n > 0) { 670 Line nextLine = pos.getNextLine(); 671 if (nextLine != null) 672 pos.setLine(nextLine); 673 else 674 break; 675 } 676 pos.setOffset(pos.getLineLength()); 677 editor.moveCaretToDotCol(); 678 } 679 return NIL; 680 } 681 }; 682 683 private static final Primitive BACKWARD_UP_LIST = 685 new Primitive("backward-up-list", PACKAGE_J, true) 686 { 687 public LispObject execute() throws ConditionThrowable 688 { 689 LispMode.backwardUpList(); 690 return NIL; 691 } 692 }; 693 694 private static final Primitive LOOKING_AT = 696 new Primitive("looking-at", PACKAGE_J, true) 697 { 698 public LispObject execute(LispObject arg) throws ConditionThrowable 699 { 700 if (arg instanceof AbstractString) { 701 String pattern = arg.getStringValue(); 702 Editor editor = Editor.currentEditor(); 703 Position dot = editor.getDot(); 704 if (dot != null) { 705 if (dot.getLine().substring(dot.getOffset()).startsWith(pattern)) 706 return T; 707 } 708 return NIL; 709 } 710 return signal(new TypeError(arg, Symbol.STRING)); 711 } 712 }; 713 714 private static final Symbol KEYWORD_GLOBAL = 715 Keyword.internKeyword("GLOBAL"); 716 private static final Symbol KEYWORD_MODE = 717 Keyword.internKeyword("MODE"); 718 private static final Symbol KEYWORD_BUFFER = 719 Keyword.internKeyword("BUFFER"); 720 private static final Symbol KEYWORD_CURRENT = 721 Keyword.internKeyword("CURRENT"); 722 723 private static final Primitive3 _VARIABLE_VALUE = 726 new Primitive3("%variable-value", PACKAGE_J, false) { 727 public LispObject execute(LispObject first, LispObject second, 728 LispObject third) throws ConditionThrowable 729 { 730 Symbol symbol = checkSymbol(first); 731 JVar jvar = JVar.getJVar(symbol); 732 Property property = jvar.getProperty(); 733 LispObject kind = second; 734 LispObject where = third; 735 final Editor editor = Editor.currentEditor(); 736 if (kind == KEYWORD_CURRENT) { 737 if (where != NIL) 738 return signal(new LispError("Bad argument: " + where + ".")); 739 final Buffer buffer = editor.getBuffer(); 740 if (property.isBooleanProperty()) 741 return buffer.getBooleanProperty(property) ? T : NIL; 742 if (property.isIntegerProperty()) 743 return number(buffer.getIntegerProperty(property)); 744 String value = buffer.getStringProperty(property); 745 return value != null ? new SimpleString(value) : NIL; 746 } 747 if (kind == KEYWORD_GLOBAL) { 748 if (property.isBooleanProperty()) 749 return preferences.getBooleanProperty(property) ? T : NIL; 750 if (property.isIntegerProperty()) 751 return number(preferences.getIntegerProperty(property)); 752 String value = preferences.getStringProperty(property); 753 return value != null ? new SimpleString(value) : NIL; 754 } 755 if (kind == KEYWORD_MODE) { 756 final Mode mode; 757 if (where == NIL) 758 mode = editor.getMode(); 759 else { 760 mode = Editor.getModeList().getModeFromModeName(where.getStringValue()); 761 if (mode == null) 762 return signal(new LispError("Unknown mode: " + where + ".")); 763 } 764 if (property.isBooleanProperty()) 765 return mode.getBooleanProperty(property) ? T : NIL; 766 if (property.isIntegerProperty()) 767 return number(mode.getIntegerProperty(property)); 768 String value = mode.getStringProperty(property); 769 return value != null ? new SimpleString(value) : NIL; 770 } 771 if (kind == KEYWORD_BUFFER) { 772 final Buffer buffer; 773 if (where != NIL) 774 buffer = checkBuffer(where); 775 else 776 buffer = editor.getBuffer(); 777 if (property.isBooleanProperty()) 778 return buffer.getBooleanProperty(property) ? T : NIL; 779 if (property.isIntegerProperty()) 780 return number(buffer.getIntegerProperty(property)); 781 String value = buffer.getStringProperty(property); 782 return value != null ? new SimpleString(value) : NIL; 783 } 784 return signal(new LispError("Invalid parameter: " + kind + ".")); 785 } 786 }; 787 788 private static final Primitive _SET_VARIABLE_VALUE = 791 new Primitive("%set-variable-value", PACKAGE_J, false) { 792 public LispObject execute(LispObject[] args) throws ConditionThrowable 793 { 794 if (args.length != 4) 795 return signal(new WrongNumberOfArgumentsException(this)); 796 Symbol symbol = checkSymbol(args[0]); 797 JVar jvar = JVar.getJVar(symbol); 798 Property property = jvar.getProperty(); 799 LispObject kind = args[1]; 800 LispObject where = args[2]; 801 LispObject newValue = args[3]; 802 if (kind == KEYWORD_GLOBAL) { 803 if (property.isBooleanProperty()) { 804 if (newValue == NIL) { 805 preferences.setProperty(property, "false"); 806 return NIL; 807 } else { 808 preferences.setProperty(property, "true"); 809 return T; 810 } 811 } else { 812 preferences.setProperty(property, newValue.getStringValue()); 813 return newValue; 814 } 815 } 816 final Editor editor = Editor.currentEditor(); 817 if (kind == KEYWORD_MODE) { 818 final Mode mode; 819 if (where == NIL) 820 mode = editor.getMode(); 821 else 822 mode = Editor.getModeList().getModeFromModeName(where.getStringValue()); 823 if (property.isBooleanProperty()) { 824 if (newValue == NIL) { 825 mode.setProperty(property, false); 826 return NIL; 827 } else { 828 mode.setProperty(property, true); 829 return T; 830 } 831 } else { 832 mode.setProperty(property, newValue.getStringValue()); 833 return newValue; 834 } 835 } 836 if (kind == KEYWORD_BUFFER) { 837 final Buffer buffer; 838 if (where != NIL) 839 buffer = checkBuffer(where); 840 else 841 buffer = editor.getBuffer(); 842 if (property.isBooleanProperty()) { 843 buffer.setProperty(property, newValue != NIL); 844 return newValue != NIL ? T : NIL; 845 } 846 if (property.isIntegerProperty()) { 847 buffer.setProperty(property, Fixnum.getValue(newValue)); 848 return newValue; 849 } 850 buffer.setProperty(property, newValue.getStringValue()); 851 return newValue; 852 } 853 return signal(new LispError("Invalid parameter: " + kind)); 854 } 855 }; 856 857 private static final Primitive0 KILL_THEME = 859 new Primitive0("kill-theme", PACKAGE_J, true) 860 { 861 public LispObject execute() 862 { 863 preferences.killTheme(); 864 return T; 865 } 866 }; 867 868 private static final Primitive0 RESTORE_FOCUS = 870 new Primitive0("restore-focus", PACKAGE_J, true) 871 { 872 public LispObject execute() 873 { 874 Editor.currentEditor().setFocusToDisplay(); 875 return T; 876 } 877 }; 878 879 private static final Primitive2 GLOBAL_MAP_KEY = 881 new Primitive2("global-map-key", PACKAGE_J, true, "key command") 882 { 883 public LispObject execute(LispObject first, LispObject second) 884 throws ConditionThrowable 885 { 886 String keyText = first.getStringValue(); 887 Object command; 888 if (second instanceof AbstractString) { 889 command = second.getStringValue(); 890 } else { 891 coerceToFunction(second); 893 command = second; 894 } 895 return KeyMap.getGlobalKeyMap().mapKey(keyText, command) ? T : NIL; 896 } 897 }; 898 899 private static final Primitive1 GLOBAL_UNMAP_KEY = 901 new Primitive1("global-unmap-key", PACKAGE_J, true, "key") 902 { 903 public LispObject execute(LispObject arg) 904 throws ConditionThrowable 905 { 906 String keyText = arg.getStringValue(); 907 return KeyMap.getGlobalKeyMap().unmapKey(keyText) ? T : NIL; 908 } 909 }; 910 911 private static final Primitive3 MAP_KEY_FOR_MODE = 913 new Primitive3("map-key-for-mode", PACKAGE_J, true, "key command mode") 914 { 915 public LispObject execute(LispObject first, LispObject second, 916 LispObject third) 917 throws ConditionThrowable 918 { 919 String keyText = first.getStringValue(); 920 Object command; 921 if (second instanceof AbstractString) { 922 command = second.getStringValue(); 923 } else { 924 coerceToFunction(second); 926 command = second; 927 } 928 String modeName = third.getStringValue(); 929 Mode mode = Editor.getModeList().getModeFromModeName(modeName); 930 if (mode == null) 931 return signal(new LispError("Unknown mode \"".concat(modeName).concat("\""))); 932 return mode.getKeyMap().mapKey(keyText, command) ? T : NIL; 933 } 934 }; 935 936 private static final Primitive2 UNMAP_KEY_FOR_MODE = 938 new Primitive2("unmap-key-for-mode", PACKAGE_J, true, "key mode") 939 { 940 public LispObject execute(LispObject first, LispObject second) 941 throws ConditionThrowable 942 { 943 String keyText = first.getStringValue(); 944 String modeName = second.getStringValue(); 945 Mode mode = Editor.getModeList().getModeFromModeName(modeName); 946 if (mode == null) 947 return signal(new LispError("Unknown mode \"".concat(modeName).concat("\""))); 948 return mode.getKeyMap().unmapKey(keyText) ? T : NIL; 949 } 950 }; 951 952 private static final Primitive2 _SET_GLOBAL_PROPERTY = 954 new Primitive2("%set-global-property", PACKAGE_J, false) { 955 public LispObject execute(LispObject first, LispObject second) 956 throws ConditionThrowable 957 { 958 String key = first.getStringValue(); 959 final String value; 960 if (second instanceof Fixnum) 961 value = String.valueOf(Fixnum.getValue(second)); 962 else 963 value = second.getStringValue(); 964 Editor.setGlobalProperty(key, value); 965 return second; 966 } 967 }; 968 969 private static final Primitive INSERT = 971 new Primitive("insert", PACKAGE_J, true, "&rest args") 972 { 973 public LispObject execute(LispObject[] args) throws ConditionThrowable 974 { 975 if (args.length == 0) 976 return NIL; 977 final Editor editor = Editor.currentEditor(); 978 if (!editor.checkReadOnly()) 979 return NIL; 980 CompoundEdit compoundEdit = editor.beginCompoundEdit(); 981 try { 982 for (int i = 0; i < args.length; i++) { 983 LispObject obj = args[i]; 984 if (obj instanceof LispCharacter) { 985 editor.insertChar(((LispCharacter)obj).getValue()); 986 } else if (obj instanceof AbstractString) { 987 editor.insertString(obj.getStringValue()); 988 } else 989 return signal(new TypeError(obj, "character or string")); 990 } 991 return NIL; 992 } 993 finally { 994 editor.endCompoundEdit(compoundEdit); 995 } 996 } 997 }; 998 999 private static final Primitive0 DELETE_REGION = 1001 new Primitive0("delete-region", PACKAGE_J, true) 1002 { 1003 public LispObject execute() throws ConditionThrowable 1004 { 1005 final Editor editor = Editor.currentEditor(); 1006 if (!editor.checkReadOnly()) 1007 return NIL; 1008 editor.deleteRegion(); 1009 return NIL; 1010 } 1011 }; 1012 1013 private static final Primitive1 SET_MARK = 1015 new Primitive1("set-mark", PACKAGE_J, true) 1016 { 1017 public LispObject execute(LispObject arg) throws ConditionThrowable 1018 { 1019 final Editor editor = Editor.currentEditor(); 1020 if (arg != NIL) 1021 editor.setMark(checkMark(arg)); 1022 else 1023 editor.unmark(); 1024 return arg; 1025 } 1026 }; 1027 1028 private static final Primitive UNDO = 1030 new Primitive("undo", PACKAGE_J, true, "&optional count") 1031 { 1032 public LispObject execute() throws ConditionThrowable 1033 { 1034 Editor.currentEditor().undo(); 1035 return NIL; 1036 } 1037 1038 public LispObject execute(LispObject arg) throws ConditionThrowable 1039 { 1040 Editor editor = Editor.currentEditor(); 1041 int count; 1042 if (arg == NIL) 1043 count = 1; 1044 else 1045 count = Fixnum.getValue(arg); 1046 for (int i = 0; i < count; i++) 1047 editor.undo(); 1048 return NIL; 1049 } 1050 }; 1051 1052 private static final Primitive0 BEGIN_COMPOUND_EDIT = 1054 new Primitive0("begin-compound-edit", PACKAGE_J, false) 1055 { 1056 public LispObject execute() 1057 { 1058 return new JavaObject(Editor.currentEditor().beginCompoundEdit()); 1059 } 1060 }; 1061 1062 private static final Primitive1 END_COMPOUND_EDIT = 1064 new Primitive1("end-compound-edit", PACKAGE_J, false) 1065 { 1066 public LispObject execute(LispObject arg) throws ConditionThrowable 1067 { 1068 try { 1069 CompoundEdit compoundEdit = 1070 (CompoundEdit ) ((JavaObject)arg).getObject(); 1071 Editor.currentEditor().endCompoundEdit(compoundEdit); 1072 return NIL; 1073 } 1074 catch (ClassCastException e) { 1075 return signal(new TypeError(arg, "compound edit")); 1076 } 1077 } 1078 }; 1079 1080 private static final Primitive1 _LOG_DEBUG = 1082 new Primitive1("%log-debug", PACKAGE_J, false) 1083 { 1084 public LispObject execute(LispObject arg) throws ConditionThrowable 1085 { 1086 Log.debug(arg.getStringValue()); 1087 return arg; 1088 } 1089 }; 1090 1091 private static final Primitive0 GET_LAST_EVENT_INTERNAL_TIME = 1093 new Primitive0("get-last-event-internal-time", PACKAGE_J, true) 1094 { 1095 public LispObject execute() throws ConditionThrowable 1096 { 1097 return number(Dispatcher.getLastEventMillis()); 1098 } 1099 }; 1100 1101 public static void invokeOpenFileHook(Buffer buffer) 1102 { 1103 try { 1104 Primitives.FUNCALL.execute(PACKAGE_J.intern("INVOKE-HOOK"), 1105 PACKAGE_J.intern("OPEN-FILE-HOOK"), 1106 new JavaObject(buffer)); 1107 } 1108 catch (Throwable t) { 1109 Log.debug(t); 1110 } 1111 } 1112 1113 public static void invokeBufferActivatedHook(Buffer buffer) 1114 { 1115 if (buffer != null) { 1116 try { 1117 Primitives.FUNCALL.execute(PACKAGE_J.intern("INVOKE-HOOK"), 1118 PACKAGE_J.intern("BUFFER-ACTIVATED-HOOK"), 1119 new JavaObject(buffer)); 1120 } 1121 catch (Throwable t) { 1122 Log.debug(t); 1123 } 1124 } 1125 } 1126 1127 public static void invokeAfterSaveHook(Buffer buffer) 1128 { 1129 try { 1130 Primitives.FUNCALL.execute(PACKAGE_J.intern("INVOKE-HOOK"), 1131 PACKAGE_J.intern("AFTER-SAVE-HOOK"), 1132 new JavaObject(buffer)); 1133 } 1134 catch (Throwable t) { 1135 Log.debug(t); 1136 } 1137 } 1138 1139 public static void invokeLispShellStartupHook(Buffer buffer, String command) 1140 { 1141 try { 1142 Primitives.FUNCALL.execute(PACKAGE_J.intern("INVOKE-HOOK"), 1143 PACKAGE_J.intern("LISP-SHELL-STARTUP-HOOK"), 1144 new JavaObject(buffer), 1145 new SimpleString(command)); 1146 } 1147 catch (Throwable t) { 1148 Log.debug(t); 1149 } 1150 } 1151 1152 public static final Primitive1 INVOKE_LATER = 1154 new Primitive1("invoke-later", PACKAGE_J, true) 1155 { 1156 public LispObject execute(LispObject arg) throws ConditionThrowable 1157 { 1158 final LispObject fun; 1159 if (arg instanceof Symbol) 1160 fun = arg.getSymbolFunction(); 1161 else 1162 fun = arg; 1163 if (fun instanceof Function || fun instanceof GenericFunction) { 1164 Runnable r = new Runnable () { 1165 public void run() 1166 { 1167 try { 1168 funcall0(fun, LispThread.currentThread()); 1169 } 1170 catch (Throwable t) { 1171 Log.error(t); 1172 } 1173 } 1174 }; 1175 SwingUtilities.invokeLater(r); 1176 return NIL; 1177 } 1178 return signal(new UndefinedFunction(arg)); 1179 } 1180 }; 1181 1182 private static final Primitive MAKE_BUFFER_STREAM = 1184 new Primitive("make-buffer-stream", PACKAGE_J, true) 1185 { 1186 public LispObject execute() throws ConditionThrowable 1187 { 1188 return new BufferStream(new Buffer(0)); 1189 } 1190 1191 public LispObject execute(LispObject arg) throws ConditionThrowable 1192 { 1193 return new BufferStream(checkBuffer(arg)); 1194 } 1195 }; 1196 1197 private static final Primitive1 BUFFER_STREAM_BUFFER = 1199 new Primitive1("buffer-stream-buffer", PACKAGE_J, true) 1200 { 1201 public LispObject execute(LispObject arg) throws ConditionThrowable 1202 { 1203 if (arg instanceof BufferStream) 1204 return new JavaObject(((BufferStream)arg).getBuffer()); 1205 return signal(new TypeError(arg, "BUFFER-STREAM")); 1206 } 1207 }; 1208 1209 private static final Primitive POP_TO_BUFFER = 1211 new Primitive("pop-to-buffer", PACKAGE_J, true) 1212 { 1213 public LispObject execute(LispObject arg) throws ConditionThrowable 1214 { 1215 if (arg != NIL) { 1216 Buffer buffer = checkBuffer(arg); 1217 Editor editor = Editor.currentEditor(); 1218 editor.makeNext(buffer); 1219 editor.activateInOtherWindow(buffer); 1220 } 1221 return arg; 1222 } 1223 }; 1224 1225 private static final Primitive switch_TO_BUFFER = 1227 new Primitive("switch-to-buffer", PACKAGE_J, true) 1228 { 1229 public LispObject execute(LispObject arg) throws ConditionThrowable 1230 { 1231 Buffer buffer = checkBuffer(arg); 1232 Editor editor = Editor.currentEditor(); 1233 editor.makeNext(buffer); 1234 editor.activate(buffer); 1235 return arg; 1236 } 1237 }; 1238 1239 private static final Primitive STATUS = 1241 new Primitive("status", PACKAGE_J, true, "string") 1242 { 1243 public LispObject execute(LispObject arg) throws ConditionThrowable 1244 { 1245 if (arg instanceof AbstractString) { 1246 final String s = ((AbstractString)arg).getStringValue(); 1247 Runnable r = new Runnable () { 1248 public void run() 1249 { 1250 try { 1251 Editor.currentEditor().status(s); 1252 } 1253 catch (Throwable t) { 1254 Log.error(t); 1255 } 1256 } 1257 }; 1258 SwingUtilities.invokeLater(r); 1259 return T; 1260 } 1261 return signal(new TypeError(arg, Symbol.STRING)); 1262 } 1263 1264 public LispObject execute(LispObject first, LispObject second) 1265 throws ConditionThrowable 1266 { 1267 if (first instanceof AbstractString) { 1268 final String s = ((AbstractString)first).getStringValue(); 1269 final Editor editor = checkEditor(second); 1270 Runnable r = new Runnable () { 1271 public void run() 1272 { 1273 try { 1274 editor.status(s); 1275 } 1276 catch (Throwable t) { 1277 Log.error(t); 1278 } 1279 } 1280 }; 1281 SwingUtilities.invokeLater(r); 1282 return T; 1283 } 1284 return signal(new TypeError(first, Symbol.STRING)); 1285 } 1286 }; 1287 1288 private static final Primitive _SEARCH = 1290 new Primitive("%search", PACKAGE_J, false, 1291 "pattern direction regexp-p buffer start ignore-case-p whole-words-only-p") 1292 { 1293 public LispObject execute(LispObject[] args) throws ConditionThrowable 1294 { 1295 if (args.length != 7) 1296 return signal(new WrongNumberOfArgumentsException(this)); 1297 final String pattern; 1298 if (args[0] instanceof AbstractString) 1299 pattern = args[0].getStringValue(); 1300 else 1301 return signal(new TypeError(args[0], Symbol.STRING)); 1302 final boolean backward; 1303 Symbol direction = checkSymbol(args[1]); 1304 if (direction == NIL || direction.getName().equals("BACKWARD")) 1305 backward = true; 1306 else if (direction.getName().equals("FORWARD")) 1307 backward = false; 1308 else 1309 return signal(new LispError("Invalid direction " + direction.writeToString())); 1310 final Buffer buffer = checkBuffer(args[3]); 1311 final Position start; 1312 if (args[4] == NIL) 1313 start = Editor.currentEditor().getDot(); 1314 else 1315 start = checkMark(args[4]); 1316 final boolean ignoreCase = (args[5] != NIL); 1317 final boolean wholeWordsOnly = (args[6] != NIL); 1318 Search search = 1319 new Search(pattern, ignoreCase, wholeWordsOnly); 1320 final Position pos; 1321 if (args[2] != NIL) { 1322 try { 1323 search.setREFromPattern(); 1324 } 1325 catch (REException e) { 1326 return signal(new LispError("Invalid regular expression: \"" + 1327 pattern + '"')); 1328 } 1329 if (backward) 1330 pos = search.reverseFindRegExp(buffer, start); 1331 else 1332 pos = search.findRegExp(buffer, start); 1333 } else { 1334 if (backward) 1335 pos = search.reverseFindString(buffer, start); 1336 else 1337 pos = search.findString(buffer, start); 1338 } 1339 return pos != null ? new JavaObject(pos) : NIL; 1340 } 1341 }; 1342 1343 private static final Primitive FIND_FILE_BUFFER = 1345 new Primitive("find-file-buffer", PACKAGE_J, true, "pathname") 1346 { 1347 public LispObject execute(LispObject arg) throws ConditionThrowable 1348 { 1349 final Pathname pathname = Pathname.coerceToPathname(arg); 1350 final String namestring = pathname.getNamestring(); 1351 if (namestring != null) { 1352 final Editor editor = Editor.currentEditor(); 1353 final Buffer buffer = editor.getBuffer(File.getInstance(namestring)); 1354 if (buffer != null) 1355 return new JavaObject(buffer); 1356 } 1357 return NIL; 1358 } 1359 }; 1360 1361 private static final Primitive CURRENT_DEFUN = 1363 new Primitive("defun-at-point", PACKAGE_J, true, "") 1364 { 1365 public LispObject execute() throws ConditionThrowable 1366 { 1367 String s = LispMode.getCurrentDefun(Editor.currentEditor()); 1368 return s != null ? new SimpleString(s) : NIL; 1369 } 1370 }; 1371 1372 private static final Primitive FORWARD_SEXP = 1374 new Primitive("forward-sexp", PACKAGE_J, true, "") 1375 { 1376 public LispObject execute() throws ConditionThrowable 1377 { 1378 LispMode.forwardSexp(); 1379 return NIL; 1380 } 1381 }; 1382 1383 private static final Primitive BACKWARD_SEXP = 1385 new Primitive("backward-sexp", PACKAGE_J, true, "") 1386 { 1387 public LispObject execute() throws ConditionThrowable 1388 { 1389 LispMode.backwardSexp(); 1390 return NIL; 1391 } 1392 }; 1393 1394 static { 1395 for (Iterator it = Property.iterator(); it.hasNext();) 1396 JVar.addVariableForProperty((Property)it.next()); 1397 } 1398} 1399 | Popular Tags |