KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > j > LispMode


1 /*
2  * LispMode.java
3  *
4  * Copyright (C) 1998-2004 Peter Graves
5  * $Id: LispMode.java,v 1.82 2004/09/13 13:49:09 piso Exp $
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 (at your option) 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
22 package org.armedbear.j;
23
24 import java.awt.event.KeyEvent JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
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 JavaDoc displayName)
44     {
45         super(id, displayName);
46     }
47
48     public static Mode getMode()
49     {
50         return mode;
51     }
52
53     public String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc definers = new HashMap JavaDoc();
152
153     static {
154         String JavaDoc[] strings = new String JavaDoc[] {
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         // SBCL
162
definers.put("def!struct", "defstruct");
163         definers.put("defmacro-mundanely", "defmacro");
164         definers.put("def!macro", "defmacro");
165         // Slime
166
definers.put("defslimefun", "defun");
167         definers.put("definterface", "defgeneric");
168         definers.put("defimplementation", "defmethod");
169     }
170
171     public static final String JavaDoc translateDefiner(String JavaDoc s)
172     {
173         if (s.length() >= 5 && s.startsWith("def"))
174             return (String JavaDoc) definers.get(s);
175         return null;
176     }
177
178     public boolean isInQuote(Buffer buffer, Position pos)
179     {
180         // This implementation only considers the current line.
181
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                 // Escape.
188
++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 JavaDoc[] specials = new String JavaDoc[] {
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 JavaDoc[] elispSpecials = new String JavaDoc[] {
213         "while"
214     };
215
216     private final String JavaDoc[] hemlockSpecials = new String JavaDoc[] {
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 JavaDoc 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) // Top level.
241
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                 // First element of containing sexp is a list or backquote
259
// expansion.
260
return buffer.getCol(posFirst);
261             }
262             // Otherwise...
263
String JavaDoc token = gatherToken(posFirst);
264             if (token.equals("do") || token.equals("do*")) {
265                 // Skip DO/DO*.
266
Position p1 = forwardSexp(posFirst);
267                 if (p1 != null) {
268                     // Skip whitespace to get to opening '(' of variable list.
269
p1.skipWhitespace();
270                     // Skip past variable list.
271
Position p2 = forwardSexp(p1);
272                     if (p2 != null) {
273                         // Skip past end test form.
274
p2 = forwardSexp(p2);
275                         // Make sure line numbers are right for isBefore().
276
if (buffer.needsRenumbering())
277                             buffer.renumber();
278                         if (p2 != null && here.isBefore(p2)) {
279                             // This is the end test form. Indent it under the
280
// opening '(' of the variable list
281
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                     // Skip whitespace to get to opening '(' of form to be
291
// evaluated.
292
p1.skipWhitespace();
293                     // Make sure line numbers are right for isBefore().
294
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             // Not special. Indent under the second element of the containing
308
// list, if the second element is on the same line as the first.
309
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             // Any non-blank line is an acceptable model.
325
while (model != null && model.isBlank())
326                 model = model.previous();
327         } else {
328             while (model != null) {
329                 if (isAcceptableModel(model))
330                     break; // Found an acceptable model.
331
else
332                     model = model.previous();
333             }
334         }
335         return model;
336     }
337
338     private static boolean isAcceptableModel(Line model)
339     {
340         String JavaDoc 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 JavaDoc 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                         // Found unmatched '('.
388
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         // Skip whitespace and comments.
406
char c;
407         while (true) {
408             pos.skipWhitespace();
409             c = pos.getChar();
410             if (c == ';')
411                 skipComment(pos);
412             else
413                 break;
414         }
415         // Reached non-whitespace char.
416
while (true) {
417             if (c == ')')
418                 return null; // "Containing expression ends prematurely."
419
if (c == '(') {
420                 // List starting.
421
if (!pos.next())
422                     return null;
423                 // Skip whitespace and comments.
424
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                 // Skip string.
438
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         // Skip whitespace and comments.
498
char c;
499         while (true) {
500             pos.skipWhitespace();
501             c = pos.getChar();
502             if (c == ';')
503                 skipComment(pos);
504             else
505                 break;
506         }
507         // Reached non-whitespace char.
508
if (c == ')')
509             return null; // "Containing expression ends prematurely."
510
if (c == '(') {
511             // List starting.
512
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         // Otherwise...
556
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             // Top level.
570
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             // Skip whitespace and comments.
600
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     // Advances pos to start of next line.
619
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             // Move past closing parenthesis.
658
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                 // Extend selection to full lines if possible.
695
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 JavaDoc trim = end.getLine().substring(end.getOffset()).trim();
700                     if (trim.length() == 0 || trim.charAt(0) == ';') {
701                         // Extend selection to complete lines.
702
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         // Go back to original starting point.
743
pos.moveTo(saved);
744         while (pos.getOffset() > 0) {
745             // Look at previous char.
746
pos.prev();
747             char c = pos.getChar();
748             if (c == '(' || c == ')')
749                 return pos;
750         }
751         // Go back to original starting point.
752
pos.moveTo(saved);
753         final int limit = pos.getLineLength() - 1;
754         while (pos.getOffset() < limit) {
755             // Look at next char.
756
pos.next();
757             char c = pos.getChar();
758             if (c == '(' || c == ')')
759                 return pos;
760             if (c == ';')
761                 return null; // The rest of the line is a comment.
762
}
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 JavaDoc 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 JavaDoc getDefunName(String JavaDoc s)
813     {
814         StringTokenizer JavaDoc st = new StringTokenizer JavaDoc(s);
815         int count = st.countTokens();
816         if (count >= 2) {
817             // Skip first token.
818
st.nextToken();
819             // Return second token.
820
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 JavaDoc defun = getCurrentDefun(editor);
834             if (defun != null) {
835                 String JavaDoc 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 JavaDoc defun = getCurrentDefun(editor);
858             if (defun != null) {
859                 String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc map;
1021
1022    public static void hyperspec()
1023    {
1024        hyperspec(null);
1025    }
1026
1027    public static void hyperspec(String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc();
1065            Line line = buf.getFirstLine();
1066            while (true) {
1067                String JavaDoc key = line.trim().toLowerCase();
1068                line = line.next();
1069                if (line == null)
1070                    break;
1071                if (line != null) {
1072                    String JavaDoc 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 JavaDoc filename = (String JavaDoc) map.get(s.toLowerCase());
1082        if (filename == null) {
1083            editor.status("No entry for \"" + s + '"');
1084            return;
1085        }
1086        String JavaDoc rootPath = rootDir.canonicalPath();
1087        File dataDir = File.getInstance(rootDir, "Data");
1088        File file = File.getInstance(dataDir, filename);
1089        WebBuffer buf = null;
1090        // Look for existing buffer.
1091
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