Source Code Cross Referenced for ConsoleReader.java in  » Development » jLine » jline » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Development » jLine » jline 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
0003:         *
0004:         * This software is distributable under the BSD license. See the terms of the
0005:         * BSD license in the documentation provided with this software.
0006:         */
0007:        package jline;
0008:
0009:        import java.awt.*;
0010:        import java.awt.datatransfer.*;
0011:        import java.awt.event.ActionListener;
0012:
0013:        import java.io.*;
0014:        import java.util.*;
0015:        import java.util.List;
0016:
0017:        /**
0018:         * A reader for console applications. It supports custom tab-completion,
0019:         * saveable command history, and command line editing. On some platforms,
0020:         * platform-specific commands will need to be issued before the reader will
0021:         * function properly. See {@link Terminal#initializeTerminal} for convenience
0022:         * methods for issuing platform-specific setup commands.
0023:         *
0024:         * @author <a href="mailto:mwp1@cornell.edu">Marc Prud'hommeaux</a>
0025:         */
0026:        public class ConsoleReader implements  ConsoleOperations {
0027:
0028:            final static int TAB_WIDTH = 4;
0029:
0030:            String prompt;
0031:
0032:            private boolean useHistory = true;
0033:
0034:            private boolean usePagination = false;
0035:
0036:            public static final String CR = System
0037:                    .getProperty("line.separator");
0038:
0039:            private static ResourceBundle loc = ResourceBundle
0040:                    .getBundle(CandidateListCompletionHandler.class.getName());
0041:
0042:            /**
0043:             * Map that contains the operation name to keymay operation mapping.
0044:             */
0045:            public static SortedMap KEYMAP_NAMES;
0046:
0047:            static {
0048:                Map names = new TreeMap();
0049:
0050:                names.put("MOVE_TO_BEG", new Short(MOVE_TO_BEG));
0051:                names.put("MOVE_TO_END", new Short(MOVE_TO_END));
0052:                names.put("PREV_CHAR", new Short(PREV_CHAR));
0053:                names.put("NEWLINE", new Short(NEWLINE));
0054:                names.put("KILL_LINE", new Short(KILL_LINE));
0055:                names.put("PASTE", new Short(PASTE));
0056:                names.put("CLEAR_SCREEN", new Short(CLEAR_SCREEN));
0057:                names.put("NEXT_HISTORY", new Short(NEXT_HISTORY));
0058:                names.put("PREV_HISTORY", new Short(PREV_HISTORY));
0059:                names.put("START_OF_HISTORY", new Short(START_OF_HISTORY));
0060:                names.put("END_OF_HISTORY", new Short(END_OF_HISTORY));
0061:                names.put("REDISPLAY", new Short(REDISPLAY));
0062:                names.put("KILL_LINE_PREV", new Short(KILL_LINE_PREV));
0063:                names.put("DELETE_PREV_WORD", new Short(DELETE_PREV_WORD));
0064:                names.put("NEXT_CHAR", new Short(NEXT_CHAR));
0065:                names.put("REPEAT_PREV_CHAR", new Short(REPEAT_PREV_CHAR));
0066:                names.put("SEARCH_PREV", new Short(SEARCH_PREV));
0067:                names.put("REPEAT_NEXT_CHAR", new Short(REPEAT_NEXT_CHAR));
0068:                names.put("SEARCH_NEXT", new Short(SEARCH_NEXT));
0069:                names.put("PREV_SPACE_WORD", new Short(PREV_SPACE_WORD));
0070:                names.put("TO_END_WORD", new Short(TO_END_WORD));
0071:                names.put("REPEAT_SEARCH_PREV", new Short(REPEAT_SEARCH_PREV));
0072:                names.put("PASTE_PREV", new Short(PASTE_PREV));
0073:                names.put("REPLACE_MODE", new Short(REPLACE_MODE));
0074:                names.put("SUBSTITUTE_LINE", new Short(SUBSTITUTE_LINE));
0075:                names.put("TO_PREV_CHAR", new Short(TO_PREV_CHAR));
0076:                names.put("NEXT_SPACE_WORD", new Short(NEXT_SPACE_WORD));
0077:                names.put("DELETE_PREV_CHAR", new Short(DELETE_PREV_CHAR));
0078:                names.put("ADD", new Short(ADD));
0079:                names.put("PREV_WORD", new Short(PREV_WORD));
0080:                names.put("CHANGE_META", new Short(CHANGE_META));
0081:                names.put("DELETE_META", new Short(DELETE_META));
0082:                names.put("END_WORD", new Short(END_WORD));
0083:                names.put("NEXT_CHAR", new Short(NEXT_CHAR));
0084:                names.put("INSERT", new Short(INSERT));
0085:                names.put("REPEAT_SEARCH_NEXT", new Short(REPEAT_SEARCH_NEXT));
0086:                names.put("PASTE_NEXT", new Short(PASTE_NEXT));
0087:                names.put("REPLACE_CHAR", new Short(REPLACE_CHAR));
0088:                names.put("SUBSTITUTE_CHAR", new Short(SUBSTITUTE_CHAR));
0089:                names.put("TO_NEXT_CHAR", new Short(TO_NEXT_CHAR));
0090:                names.put("UNDO", new Short(UNDO));
0091:                names.put("NEXT_WORD", new Short(NEXT_WORD));
0092:                names.put("DELETE_NEXT_CHAR", new Short(DELETE_NEXT_CHAR));
0093:                names.put("CHANGE_CASE", new Short(CHANGE_CASE));
0094:                names.put("COMPLETE", new Short(COMPLETE));
0095:                names.put("EXIT", new Short(EXIT));
0096:                names.put("CLEAR_LINE", new Short(CLEAR_LINE));
0097:
0098:                KEYMAP_NAMES = new TreeMap(Collections.unmodifiableMap(names));
0099:            }
0100:
0101:            /**
0102:             * The map for logical operations.
0103:             */
0104:            private final short[] keybindings;
0105:
0106:            /**
0107:             * If true, issue an audible keyboard bell when appropriate.
0108:             */
0109:            private boolean bellEnabled = true;
0110:
0111:            /**
0112:             * The current character mask.
0113:             */
0114:            private Character mask = null;
0115:
0116:            /**
0117:             * The null mask.
0118:             */
0119:            private static final Character NULL_MASK = new Character((char) 0);
0120:
0121:            /**
0122:             * The number of tab-completion candidates above which a warning will be
0123:             * prompted before showing all the candidates.
0124:             */
0125:            private int autoprintThreshhold = Integer.getInteger(
0126:                    "jline.completion.threshold", 100).intValue(); // same default as
0127:
0128:            // bash
0129:
0130:            /**
0131:             * The Terminal to use.
0132:             */
0133:            private final Terminal terminal;
0134:
0135:            private CompletionHandler completionHandler = new CandidateListCompletionHandler();
0136:
0137:            InputStream in;
0138:
0139:            final Writer out;
0140:
0141:            final CursorBuffer buf = new CursorBuffer();
0142:
0143:            static PrintWriter debugger;
0144:
0145:            History history = new History();
0146:
0147:            final List completors = new LinkedList();
0148:
0149:            private Character echoCharacter = null;
0150:
0151:            private Map triggeredActions = new HashMap();
0152:
0153:            /**
0154:             * Adding a triggered Action allows to give another curse of action
0155:             * if a character passed the preprocessing.
0156:             * 
0157:             * Say you want to close the application if the user enter q.
0158:             * addTriggerAction('q', new ActionListener(){ System.exit(0); });
0159:             * would do the trick.
0160:             * 
0161:             * @param c
0162:             * @param listener
0163:             */
0164:            public void addTriggeredAction(char c, ActionListener listener) {
0165:                triggeredActions.put(new Character(c), listener);
0166:            }
0167:
0168:            /**
0169:             * Create a new reader using {@link FileDescriptor#in} for input and
0170:             * {@link System#out} for output. {@link FileDescriptor#in} is used because
0171:             * it has a better chance of being unbuffered.
0172:             */
0173:            public ConsoleReader() throws IOException {
0174:                this (new FileInputStream(FileDescriptor.in), new PrintWriter(
0175:                        new OutputStreamWriter(System.out, System.getProperty(
0176:                                "jline.WindowsTerminal.output.encoding", System
0177:                                        .getProperty("file.encoding")))));
0178:            }
0179:
0180:            /**
0181:             * Create a new reader using the specified {@link InputStream} for input and
0182:             * the specific writer for output, using the default keybindings resource.
0183:             */
0184:            public ConsoleReader(final InputStream in, final Writer out)
0185:                    throws IOException {
0186:                this (in, out, null);
0187:            }
0188:
0189:            public ConsoleReader(final InputStream in, final Writer out,
0190:                    final InputStream bindings) throws IOException {
0191:                this (in, out, bindings, Terminal.getTerminal());
0192:            }
0193:
0194:            /**
0195:             * Create a new reader.
0196:             *
0197:             * @param in
0198:             *            the input
0199:             * @param out
0200:             *            the output
0201:             * @param bindings
0202:             *            the key bindings to use
0203:             * @param term
0204:             *            the terminal to use
0205:             */
0206:            public ConsoleReader(InputStream in, Writer out,
0207:                    InputStream bindings, Terminal term) throws IOException {
0208:                this .terminal = term;
0209:                setInput(in);
0210:                this .out = out;
0211:                if (bindings == null) {
0212:                    try {
0213:                        String bindingFile = System.getProperty(
0214:                                "jline.keybindings", new File(System
0215:                                        .getProperty("user.home",
0216:                                                ".jlinebindings.properties"))
0217:                                        .getAbsolutePath());
0218:
0219:                        if (new File(bindingFile).isFile()) {
0220:                            bindings = new FileInputStream(
0221:                                    new File(bindingFile));
0222:                        }
0223:                    } catch (Exception e) {
0224:                        // swallow exceptions with option debugging
0225:                        if (debugger != null) {
0226:                            e.printStackTrace(debugger);
0227:                        }
0228:                    }
0229:                }
0230:
0231:                if (bindings == null) {
0232:                    bindings = terminal.getDefaultBindings();
0233:                }
0234:
0235:                this .keybindings = new short[Character.MAX_VALUE * 2];
0236:
0237:                Arrays.fill(this .keybindings, UNKNOWN);
0238:
0239:                /**
0240:                 * Loads the key bindings. Bindings file is in the format:
0241:                 *
0242:                 * keycode: operation name
0243:                 */
0244:                if (bindings != null) {
0245:                    Properties p = new Properties();
0246:                    p.load(bindings);
0247:                    bindings.close();
0248:
0249:                    for (Iterator i = p.keySet().iterator(); i.hasNext();) {
0250:                        String val = (String) i.next();
0251:
0252:                        try {
0253:                            Short code = new Short(val);
0254:                            String op = (String) p.getProperty(val);
0255:
0256:                            Short opval = (Short) KEYMAP_NAMES.get(op);
0257:
0258:                            if (opval != null) {
0259:                                keybindings[code.shortValue()] = opval
0260:                                        .shortValue();
0261:                            }
0262:                        } catch (NumberFormatException nfe) {
0263:                            consumeException(nfe);
0264:                        }
0265:                    }
0266:
0267:                    // hardwired arrow key bindings
0268:                    // keybindings[VK_UP] = PREV_HISTORY;
0269:                    // keybindings[VK_DOWN] = NEXT_HISTORY;
0270:                    // keybindings[VK_LEFT] = PREV_CHAR;
0271:                    // keybindings[VK_RIGHT] = NEXT_CHAR;
0272:                }
0273:            }
0274:
0275:            public Terminal getTerminal() {
0276:                return this .terminal;
0277:            }
0278:
0279:            /**
0280:             * Set the stream for debugging. Development use only.
0281:             */
0282:            public void setDebug(final PrintWriter debugger) {
0283:                ConsoleReader.debugger = debugger;
0284:            }
0285:
0286:            /**
0287:             * Set the stream to be used for console input.
0288:             */
0289:            public void setInput(final InputStream in) {
0290:                this .in = in;
0291:            }
0292:
0293:            /**
0294:             * Returns the stream used for console input.
0295:             */
0296:            public InputStream getInput() {
0297:                return this .in;
0298:            }
0299:
0300:            /**
0301:             * Read the next line and return the contents of the buffer.
0302:             */
0303:            public String readLine() throws IOException {
0304:                return readLine((String) null);
0305:            }
0306:
0307:            /**
0308:             * Read the next line with the specified character mask. If null, then
0309:             * characters will be echoed. If 0, then no characters will be echoed.
0310:             */
0311:            public String readLine(final Character mask) throws IOException {
0312:                return readLine(null, mask);
0313:            }
0314:
0315:            /**
0316:             * @param bellEnabled
0317:             *            if true, enable audible keyboard bells if an alert is
0318:             *            required.
0319:             */
0320:            public void setBellEnabled(final boolean bellEnabled) {
0321:                this .bellEnabled = bellEnabled;
0322:            }
0323:
0324:            /**
0325:             * @return true is audible keyboard bell is enabled.
0326:             */
0327:            public boolean getBellEnabled() {
0328:                return this .bellEnabled;
0329:            }
0330:
0331:            /**
0332:             * Query the terminal to find the current width;
0333:             *
0334:             * @see Terminal#getTerminalWidth
0335:             * @return the width of the current terminal.
0336:             */
0337:            public int getTermwidth() {
0338:                return Terminal.setupTerminal().getTerminalWidth();
0339:            }
0340:
0341:            /**
0342:             * Query the terminal to find the current width;
0343:             *
0344:             * @see Terminal#getTerminalHeight
0345:             *
0346:             * @return the height of the current terminal.
0347:             */
0348:            public int getTermheight() {
0349:                return Terminal.setupTerminal().getTerminalHeight();
0350:            }
0351:
0352:            /**
0353:             * @param autoprintThreshhold
0354:             *            the number of candidates to print without issuing a warning.
0355:             */
0356:            public void setAutoprintThreshhold(final int autoprintThreshhold) {
0357:                this .autoprintThreshhold = autoprintThreshhold;
0358:            }
0359:
0360:            /**
0361:             * @return the number of candidates to print without issing a warning.
0362:             */
0363:            public int getAutoprintThreshhold() {
0364:                return this .autoprintThreshhold;
0365:            }
0366:
0367:            int getKeyForAction(short logicalAction) {
0368:                for (int i = 0; i < keybindings.length; i++) {
0369:                    if (keybindings[i] == logicalAction) {
0370:                        return i;
0371:                    }
0372:                }
0373:
0374:                return -1;
0375:            }
0376:
0377:            /**
0378:             * Clear the echoed characters for the specified character code.
0379:             */
0380:            int clearEcho(int c) throws IOException {
0381:                // if the terminal is not echoing, then just return...
0382:                if (!terminal.getEcho()) {
0383:                    return 0;
0384:                }
0385:
0386:                // otherwise, clear
0387:                int num = countEchoCharacters((char) c);
0388:                back(num);
0389:                drawBuffer(num);
0390:
0391:                return num;
0392:            }
0393:
0394:            int countEchoCharacters(char c) {
0395:                // tabs as special: we need to determine the number of spaces
0396:                // to cancel based on what out current cursor position is
0397:                if (c == 9) {
0398:                    int tabstop = 8; // will this ever be different?
0399:                    int position = getCursorPosition();
0400:
0401:                    return tabstop - (position % tabstop);
0402:                }
0403:
0404:                return getPrintableCharacters(c).length();
0405:            }
0406:
0407:            /**
0408:             * Return the number of characters that will be printed when the specified
0409:             * character is echoed to the screen. Adapted from cat by Torbjorn Granlund,
0410:             * as repeated in stty by David MacKenzie.
0411:             */
0412:            StringBuffer getPrintableCharacters(char ch) {
0413:                StringBuffer sbuff = new StringBuffer();
0414:
0415:                if (ch >= 32) {
0416:                    if (ch < 127) {
0417:                        sbuff.append(ch);
0418:                    } else if (ch == 127) {
0419:                        sbuff.append('^');
0420:                        sbuff.append('?');
0421:                    } else {
0422:                        sbuff.append('M');
0423:                        sbuff.append('-');
0424:
0425:                        if (ch >= (128 + 32)) {
0426:                            if (ch < (128 + 127)) {
0427:                                sbuff.append((char) (ch - 128));
0428:                            } else {
0429:                                sbuff.append('^');
0430:                                sbuff.append('?');
0431:                            }
0432:                        } else {
0433:                            sbuff.append('^');
0434:                            sbuff.append((char) (ch - 128 + 64));
0435:                        }
0436:                    }
0437:                } else {
0438:                    sbuff.append('^');
0439:                    sbuff.append((char) (ch + 64));
0440:                }
0441:
0442:                return sbuff;
0443:            }
0444:
0445:            int getCursorPosition() {
0446:                // FIXME: does not handle anything but a line with a prompt
0447:                // absolute position
0448:                return ((prompt == null) ? 0 : prompt.length()) + buf.cursor;
0449:            }
0450:
0451:            public String readLine(final String prompt) throws IOException {
0452:                return readLine(prompt, null);
0453:            }
0454:
0455:            /**
0456:             * The default prompt that will be issued.
0457:             */
0458:            public void setDefaultPrompt(String prompt) {
0459:                this .prompt = prompt;
0460:            }
0461:
0462:            /**
0463:             * The default prompt that will be issued.
0464:             */
0465:            public String getDefaultPrompt() {
0466:                return prompt;
0467:            }
0468:
0469:            /**
0470:             * Read a line from the <i>in</i> {@link InputStream}, and return the line
0471:             * (without any trailing newlines).
0472:             *
0473:             * @param prompt
0474:             *            the prompt to issue to the console, may be null.
0475:             * @return a line that is read from the terminal, or null if there was null
0476:             *         input (e.g., <i>CTRL-D</i> was pressed).
0477:             */
0478:            public String readLine(final String prompt, final Character mask)
0479:                    throws IOException {
0480:                this .mask = mask;
0481:                if (prompt != null)
0482:                    this .prompt = prompt;
0483:
0484:                try {
0485:                    terminal.beforeReadLine(this , this .prompt, mask);
0486:
0487:                    if ((this .prompt != null) && (this .prompt.length() > 0)) {
0488:                        out.write(this .prompt);
0489:                        out.flush();
0490:                    }
0491:
0492:                    // if the terminal is unsupported, just use plain-java reading
0493:                    if (!terminal.isSupported()) {
0494:                        return readLine(in);
0495:                    }
0496:
0497:                    while (true) {
0498:                        int[] next = readBinding();
0499:
0500:                        if (next == null) {
0501:                            return null;
0502:                        }
0503:
0504:                        int c = next[0];
0505:                        int code = next[1];
0506:
0507:                        if (c == -1) {
0508:                            return null;
0509:                        }
0510:
0511:                        boolean success = true;
0512:
0513:                        switch (code) {
0514:                        case EXIT: // ctrl-d
0515:
0516:                            if (buf.buffer.length() == 0) {
0517:                                return null;
0518:                            }
0519:                            break;
0520:
0521:                        case COMPLETE: // tab
0522:                            success = complete();
0523:                            break;
0524:
0525:                        case MOVE_TO_BEG:
0526:                            success = setCursorPosition(0);
0527:                            break;
0528:
0529:                        case KILL_LINE: // CTRL-K
0530:                            success = killLine();
0531:                            break;
0532:
0533:                        case CLEAR_SCREEN: // CTRL-L
0534:                            success = clearScreen();
0535:                            break;
0536:
0537:                        case KILL_LINE_PREV: // CTRL-U
0538:                            success = resetLine();
0539:                            break;
0540:
0541:                        case NEWLINE: // enter
0542:                            moveToEnd();
0543:                            printNewline(); // output newline
0544:                            return finishBuffer();
0545:
0546:                        case DELETE_PREV_CHAR: // backspace
0547:                            success = backspace();
0548:                            break;
0549:
0550:                        case DELETE_NEXT_CHAR: // delete
0551:                            success = deleteCurrentCharacter();
0552:                            break;
0553:
0554:                        case MOVE_TO_END:
0555:                            success = moveToEnd();
0556:                            break;
0557:
0558:                        case PREV_CHAR:
0559:                            success = moveCursor(-1) != 0;
0560:                            break;
0561:
0562:                        case NEXT_CHAR:
0563:                            success = moveCursor(1) != 0;
0564:                            break;
0565:
0566:                        case NEXT_HISTORY:
0567:                            success = moveHistory(true);
0568:                            break;
0569:
0570:                        case PREV_HISTORY:
0571:                            success = moveHistory(false);
0572:                            break;
0573:
0574:                        case REDISPLAY:
0575:                            break;
0576:
0577:                        case PASTE:
0578:                            success = paste();
0579:                            break;
0580:
0581:                        case DELETE_PREV_WORD:
0582:                            success = deletePreviousWord();
0583:                            break;
0584:
0585:                        case PREV_WORD:
0586:                            success = previousWord();
0587:                            break;
0588:
0589:                        case NEXT_WORD:
0590:                            success = nextWord();
0591:                            break;
0592:
0593:                        case START_OF_HISTORY:
0594:                            success = history.moveToFirstEntry();
0595:                            if (success)
0596:                                setBuffer(history.current());
0597:                            break;
0598:
0599:                        case END_OF_HISTORY:
0600:                            success = history.moveToLastEntry();
0601:                            if (success)
0602:                                setBuffer(history.current());
0603:                            break;
0604:
0605:                        case CLEAR_LINE:
0606:                            moveInternal(-(buf.buffer.length()));
0607:                            killLine();
0608:                            break;
0609:
0610:                        case INSERT:
0611:                            buf.setOvertyping(!buf.isOvertyping());
0612:                            break;
0613:
0614:                        case UNKNOWN:
0615:                        default:
0616:                            if (c != 0) { // ignore null chars
0617:                                ActionListener action = (ActionListener) triggeredActions
0618:                                        .get(new Character((char) c));
0619:                                if (action != null)
0620:                                    action.actionPerformed(null);
0621:                                else
0622:                                    putChar(c, true);
0623:                            } else
0624:                                success = false;
0625:                        }
0626:
0627:                        if (!(success)) {
0628:                            beep();
0629:                        }
0630:
0631:                        flushConsole();
0632:                    }
0633:                } finally {
0634:                    terminal.afterReadLine(this , this .prompt, mask);
0635:                }
0636:            }
0637:
0638:            private String readLine(InputStream in) throws IOException {
0639:                StringBuffer buf = new StringBuffer();
0640:
0641:                while (true) {
0642:                    int i = in.read();
0643:
0644:                    if ((i == -1) || (i == '\n') || (i == '\r')) {
0645:                        return buf.toString();
0646:                    }
0647:
0648:                    buf.append((char) i);
0649:                }
0650:
0651:                // return new BufferedReader (new InputStreamReader (in)).readLine ();
0652:            }
0653:
0654:            /**
0655:             * Reads the console input and returns an array of the form [raw, key
0656:             * binding].
0657:             */
0658:            private int[] readBinding() throws IOException {
0659:                int c = readVirtualKey();
0660:
0661:                if (c == -1) {
0662:                    return null;
0663:                }
0664:
0665:                // extract the appropriate key binding
0666:                short code = keybindings[c];
0667:
0668:                if (debugger != null) {
0669:                    debug("    translated: " + (int) c + ": " + code);
0670:                }
0671:
0672:                return new int[] { c, code };
0673:            }
0674:
0675:            /**
0676:             * Move up or down the history tree.
0677:             *
0678:             * @param direction
0679:             *            less than 0 to move up the tree, down otherwise
0680:             */
0681:            private final boolean moveHistory(final boolean next)
0682:                    throws IOException {
0683:                if (next && !history.next()) {
0684:                    return false;
0685:                } else if (!next && !history.previous()) {
0686:                    return false;
0687:                }
0688:
0689:                setBuffer(history.current());
0690:
0691:                return true;
0692:            }
0693:
0694:            /**
0695:             * Paste the contents of the clipboard into the console buffer
0696:             *
0697:             * @return true if clipboard contents pasted
0698:             */
0699:            public boolean paste() throws IOException {
0700:                Clipboard clipboard;
0701:                try { // May throw ugly exception on system without X
0702:                    clipboard = Toolkit.getDefaultToolkit()
0703:                            .getSystemClipboard();
0704:                } catch (Exception e) {
0705:                    return false;
0706:                }
0707:
0708:                if (clipboard == null) {
0709:                    return false;
0710:                }
0711:
0712:                Transferable transferable = clipboard.getContents(null);
0713:
0714:                if (transferable == null) {
0715:                    return false;
0716:                }
0717:
0718:                try {
0719:                    Object content = transferable
0720:                            .getTransferData(DataFlavor.plainTextFlavor);
0721:
0722:                    /*
0723:                     * This fix was suggested in bug #1060649 at
0724:                     * http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056
0725:                     * to get around the deprecated DataFlavor.plainTextFlavor, but it
0726:                     * raises a UnsupportedFlavorException on Mac OS X
0727:                     */
0728:                    if (content == null) {
0729:                        try {
0730:                            content = new DataFlavor()
0731:                                    .getReaderForText(transferable);
0732:                        } catch (Exception e) {
0733:                        }
0734:                    }
0735:
0736:                    if (content == null) {
0737:                        return false;
0738:                    }
0739:
0740:                    String value;
0741:
0742:                    if (content instanceof  Reader) {
0743:                        // TODO: we might want instead connect to the input stream
0744:                        // so we can interpret individual lines
0745:                        value = "";
0746:
0747:                        String line = null;
0748:
0749:                        for (BufferedReader read = new BufferedReader(
0750:                                (Reader) content); (line = read.readLine()) != null;) {
0751:                            if (value.length() > 0) {
0752:                                value += "\n";
0753:                            }
0754:
0755:                            value += line;
0756:                        }
0757:                    } else {
0758:                        value = content.toString();
0759:                    }
0760:
0761:                    if (value == null) {
0762:                        return true;
0763:                    }
0764:
0765:                    putString(value);
0766:
0767:                    return true;
0768:                } catch (UnsupportedFlavorException ufe) {
0769:                    if (debugger != null)
0770:                        debug(ufe + "");
0771:
0772:                    return false;
0773:                }
0774:            }
0775:
0776:            /**
0777:             * Kill the buffer ahead of the current cursor position.
0778:             *
0779:             * @return true if successful
0780:             */
0781:            public boolean killLine() throws IOException {
0782:                int cp = buf.cursor;
0783:                int len = buf.buffer.length();
0784:
0785:                if (cp >= len) {
0786:                    return false;
0787:                }
0788:
0789:                int num = buf.buffer.length() - cp;
0790:                clearAhead(num);
0791:
0792:                for (int i = 0; i < num; i++) {
0793:                    buf.buffer.deleteCharAt(len - i - 1);
0794:                }
0795:
0796:                return true;
0797:            }
0798:
0799:            /**
0800:             * Clear the screen by issuing the ANSI "clear screen" code.
0801:             */
0802:            public boolean clearScreen() throws IOException {
0803:                if (!terminal.isANSISupported()) {
0804:                    return false;
0805:                }
0806:
0807:                // send the ANSI code to clear the screen
0808:                printString(((char) 27) + "[2J");
0809:                flushConsole();
0810:
0811:                // then send the ANSI code to go to position 1,1
0812:                printString(((char) 27) + "[1;1H");
0813:                flushConsole();
0814:
0815:                redrawLine();
0816:
0817:                return true;
0818:            }
0819:
0820:            /**
0821:             * Use the completors to modify the buffer with the appropriate completions.
0822:             *
0823:             * @return true if successful
0824:             */
0825:            private final boolean complete() throws IOException {
0826:                // debug ("tab for (" + buf + ")");
0827:                if (completors.size() == 0) {
0828:                    return false;
0829:                }
0830:
0831:                List candidates = new LinkedList();
0832:                String bufstr = buf.buffer.toString();
0833:                int cursor = buf.cursor;
0834:
0835:                int position = -1;
0836:
0837:                for (Iterator i = completors.iterator(); i.hasNext();) {
0838:                    Completor comp = (Completor) i.next();
0839:
0840:                    if ((position = comp.complete(bufstr, cursor, candidates)) != -1) {
0841:                        break;
0842:                    }
0843:                }
0844:
0845:                // no candidates? Fail.
0846:                if (candidates.size() == 0) {
0847:                    return false;
0848:                }
0849:
0850:                return completionHandler.complete(this , candidates, position);
0851:            }
0852:
0853:            public CursorBuffer getCursorBuffer() {
0854:                return buf;
0855:            }
0856:
0857:            /**
0858:             * Output the specified {@link Collection} in proper columns.
0859:             *
0860:             * @param stuff
0861:             *            the stuff to print
0862:             */
0863:            public void printColumns(final Collection stuff) throws IOException {
0864:                if ((stuff == null) || (stuff.size() == 0)) {
0865:                    return;
0866:                }
0867:
0868:                int width = getTermwidth();
0869:                int maxwidth = 0;
0870:
0871:                for (Iterator i = stuff.iterator(); i.hasNext(); maxwidth = Math
0872:                        .max(maxwidth, i.next().toString().length())) {
0873:                    ;
0874:                }
0875:
0876:                StringBuffer line = new StringBuffer();
0877:
0878:                int showLines;
0879:
0880:                if (usePagination)
0881:                    showLines = getTermheight() - 1; // page limit
0882:                else
0883:                    showLines = Integer.MAX_VALUE;
0884:
0885:                for (Iterator i = stuff.iterator(); i.hasNext();) {
0886:                    String cur = (String) i.next();
0887:
0888:                    if ((line.length() + maxwidth) > width) {
0889:                        printString(line.toString().trim());
0890:                        printNewline();
0891:                        line.setLength(0);
0892:                        if (--showLines == 0) { // Overflow
0893:                            printString(loc.getString("display-more"));
0894:                            flushConsole();
0895:                            int c = readVirtualKey();
0896:                            if (c == '\r' || c == '\n')
0897:                                showLines = 1; // one step forward
0898:                            else if (c != 'q')
0899:                                showLines = getTermheight() - 1; // page forward
0900:
0901:                            back(loc.getString("display-more").length());
0902:                            if (c == 'q')
0903:                                break; // cancel
0904:                        }
0905:                    }
0906:
0907:                    pad(cur, maxwidth + 3, line);
0908:                }
0909:
0910:                if (line.length() > 0) {
0911:                    printString(line.toString().trim());
0912:                    printNewline();
0913:                    line.setLength(0);
0914:                }
0915:            }
0916:
0917:            /**
0918:             * Append <i>toPad</i> to the specified <i>appendTo</i>, as well as (<i>toPad.length () -
0919:             * len</i>) spaces.
0920:             *
0921:             * @param toPad
0922:             *            the {@link String} to pad
0923:             * @param len
0924:             *            the target length
0925:             * @param appendTo
0926:             *            the {@link StringBuffer} to which to append the padded
0927:             *            {@link String}.
0928:             */
0929:            private final void pad(final String toPad, final int len,
0930:                    final StringBuffer appendTo) {
0931:                appendTo.append(toPad);
0932:
0933:                for (int i = 0; i < (len - toPad.length()); i++, appendTo
0934:                        .append(' ')) {
0935:                    ;
0936:                }
0937:            }
0938:
0939:            /**
0940:             * Add the specified {@link Completor} to the list of handlers for
0941:             * tab-completion.
0942:             *
0943:             * @param completor
0944:             *            the {@link Completor} to add
0945:             * @return true if it was successfully added
0946:             */
0947:            public boolean addCompletor(final Completor completor) {
0948:                return completors.add(completor);
0949:            }
0950:
0951:            /**
0952:             * Remove the specified {@link Completor} from the list of handlers for
0953:             * tab-completion.
0954:             *
0955:             * @param completor
0956:             *            the {@link Completor} to remove
0957:             * @return true if it was successfully removed
0958:             */
0959:            public boolean removeCompletor(final Completor completor) {
0960:                return completors.remove(completor);
0961:            }
0962:
0963:            /**
0964:             * Returns an unmodifiable list of all the completors.
0965:             */
0966:            public Collection getCompletors() {
0967:                return Collections.unmodifiableList(completors);
0968:            }
0969:
0970:            /**
0971:             * Erase the current line.
0972:             *
0973:             * @return false if we failed (e.g., the buffer was empty)
0974:             */
0975:            final boolean resetLine() throws IOException {
0976:                if (buf.cursor == 0) {
0977:                    return false;
0978:                }
0979:
0980:                backspaceAll();
0981:
0982:                return true;
0983:            }
0984:
0985:            /**
0986:             * Move the cursor position to the specified absolute index.
0987:             */
0988:            public final boolean setCursorPosition(final int position)
0989:                    throws IOException {
0990:                return moveCursor(position - buf.cursor) != 0;
0991:            }
0992:
0993:            /**
0994:             * Set the current buffer's content to the specified {@link String}. The
0995:             * visual console will be modified to show the current buffer.
0996:             *
0997:             * @param buffer
0998:             *            the new contents of the buffer.
0999:             */
1000:            private final void setBuffer(final String buffer)
1001:                    throws IOException {
1002:                // don't bother modifying it if it is unchanged
1003:                if (buffer.equals(buf.buffer.toString())) {
1004:                    return;
1005:                }
1006:
1007:                // obtain the difference between the current buffer and the new one
1008:                int sameIndex = 0;
1009:
1010:                for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1)
1011:                        && (i < l2); i++) {
1012:                    if (buffer.charAt(i) == buf.buffer.charAt(i)) {
1013:                        sameIndex++;
1014:                    } else {
1015:                        break;
1016:                    }
1017:                }
1018:
1019:                int diff = buf.buffer.length() - sameIndex;
1020:
1021:                backspace(diff); // go back for the differences
1022:                killLine(); // clear to the end of the line
1023:                buf.buffer.setLength(sameIndex); // the new length
1024:                putString(buffer.substring(sameIndex)); // append the differences
1025:            }
1026:
1027:            /**
1028:             * Clear the line and redraw it.
1029:             */
1030:            public final void redrawLine() throws IOException {
1031:                printCharacter(RESET_LINE);
1032:                flushConsole();
1033:                drawLine();
1034:            }
1035:
1036:            /**
1037:             * Output put the prompt + the current buffer
1038:             */
1039:            public final void drawLine() throws IOException {
1040:                if (prompt != null) {
1041:                    printString(prompt);
1042:                }
1043:
1044:                printString(buf.buffer.toString());
1045:
1046:                if (buf.length() != buf.cursor) // not at end of line
1047:                    back(buf.length() - buf.cursor); // sync
1048:            }
1049:
1050:            /**
1051:             * Output a platform-dependant newline.
1052:             */
1053:            public final void printNewline() throws IOException {
1054:                printString(CR);
1055:                flushConsole();
1056:            }
1057:
1058:            /**
1059:             * Clear the buffer and add its contents to the history.
1060:             *
1061:             * @return the former contents of the buffer.
1062:             */
1063:            final String finishBuffer() {
1064:                String str = buf.buffer.toString();
1065:
1066:                // we only add it to the history if the buffer is not empty
1067:                // and if mask is null, since having a mask typically means
1068:                // the string was a password. We clear the mask after this call
1069:                if (str.length() > 0) {
1070:                    if (mask == null && useHistory) {
1071:                        history.addToHistory(str);
1072:                    } else {
1073:                        mask = null;
1074:                    }
1075:                }
1076:
1077:                history.moveToEnd();
1078:
1079:                buf.buffer.setLength(0);
1080:                buf.cursor = 0;
1081:
1082:                return str;
1083:            }
1084:
1085:            /**
1086:             * Write out the specified string to the buffer and the output stream.
1087:             */
1088:            public final void putString(final String str) throws IOException {
1089:                buf.write(str);
1090:                printString(str);
1091:                drawBuffer();
1092:            }
1093:
1094:            /**
1095:             * Output the specified string to the output stream (but not the buffer).
1096:             */
1097:            public final void printString(final String str) throws IOException {
1098:                printCharacters(str.toCharArray());
1099:            }
1100:
1101:            /**
1102:             * Output the specified character, both to the buffer and the output stream.
1103:             */
1104:            private final void putChar(final int c, final boolean print)
1105:                    throws IOException {
1106:                buf.write((char) c);
1107:
1108:                if (print) {
1109:                    // no masking...
1110:                    if (mask == null) {
1111:                        printCharacter(c);
1112:                    }
1113:                    // null mask: don't print anything...
1114:                    else if (mask.charValue() == 0) {
1115:                        ;
1116:                    }
1117:                    // otherwise print the mask...
1118:                    else {
1119:                        printCharacter(mask.charValue());
1120:                    }
1121:
1122:                    drawBuffer();
1123:                }
1124:            }
1125:
1126:            /**
1127:             * Redraw the rest of the buffer from the cursor onwards. This is necessary
1128:             * for inserting text into the buffer.
1129:             *
1130:             * @param clear
1131:             *            the number of characters to clear after the end of the buffer
1132:             */
1133:            private final void drawBuffer(final int clear) throws IOException {
1134:                // debug ("drawBuffer: " + clear);
1135:                char[] chars = buf.buffer.substring(buf.cursor).toCharArray();
1136:                if (mask != null)
1137:                    Arrays.fill(chars, mask.charValue());
1138:
1139:                printCharacters(chars);
1140:
1141:                clearAhead(clear);
1142:                back(chars.length);
1143:                flushConsole();
1144:            }
1145:
1146:            /**
1147:             * Redraw the rest of the buffer from the cursor onwards. This is necessary
1148:             * for inserting text into the buffer.
1149:             */
1150:            private final void drawBuffer() throws IOException {
1151:                drawBuffer(0);
1152:            }
1153:
1154:            /**
1155:             * Clear ahead the specified number of characters without moving the cursor.
1156:             */
1157:            private final void clearAhead(final int num) throws IOException {
1158:                if (num == 0) {
1159:                    return;
1160:                }
1161:
1162:                // debug ("clearAhead: " + num);
1163:
1164:                // print blank extra characters
1165:                printCharacters(' ', num);
1166:
1167:                // we need to flush here so a "clever" console
1168:                // doesn't just ignore the redundancy of a space followed by
1169:                // a backspace.
1170:                flushConsole();
1171:
1172:                // reset the visual cursor
1173:                back(num);
1174:
1175:                flushConsole();
1176:            }
1177:
1178:            /**
1179:             * Move the visual cursor backwards without modifying the buffer cursor.
1180:             */
1181:            private final void back(final int num) throws IOException {
1182:                printCharacters(BACKSPACE, num);
1183:                flushConsole();
1184:            }
1185:
1186:            /**
1187:             * Issue an audible keyboard bell, if {@link #getBellEnabled} return true.
1188:             */
1189:            public final void beep() throws IOException {
1190:                if (!(getBellEnabled())) {
1191:                    return;
1192:                }
1193:
1194:                printCharacter(KEYBOARD_BELL);
1195:                // need to flush so the console actually beeps
1196:                flushConsole();
1197:            }
1198:
1199:            /**
1200:             * Output the specified character to the output stream without manipulating
1201:             * the current buffer.
1202:             */
1203:            private final void printCharacter(final int c) throws IOException {
1204:                if (c == '\t') {
1205:                    char cbuf[] = new char[TAB_WIDTH];
1206:                    Arrays.fill(cbuf, ' ');
1207:                    out.write(cbuf);
1208:                    return;
1209:                }
1210:
1211:                out.write(c);
1212:            }
1213:
1214:            /**
1215:             * Output the specified characters to the output stream without manipulating
1216:             * the current buffer.
1217:             */
1218:            private final void printCharacters(final char[] c)
1219:                    throws IOException {
1220:                int len = 0;
1221:                for (int i = 0; i < c.length; i++)
1222:                    if (c[i] == '\t')
1223:                        len += TAB_WIDTH;
1224:                    else
1225:                        len++;
1226:
1227:                char cbuf[];
1228:                if (len == c.length)
1229:                    cbuf = c;
1230:                else {
1231:                    cbuf = new char[len];
1232:                    int pos = 0;
1233:                    for (int i = 0; i < c.length; i++) {
1234:                        if (c[i] == '\t') {
1235:                            Arrays.fill(cbuf, pos, pos + TAB_WIDTH, ' ');
1236:                            pos += TAB_WIDTH;
1237:                        } else {
1238:                            cbuf[pos] = c[i];
1239:                            pos++;
1240:                        }
1241:                    }
1242:                }
1243:
1244:                out.write(cbuf);
1245:            }
1246:
1247:            private final void printCharacters(final char c, final int num)
1248:                    throws IOException {
1249:                if (num == 1) {
1250:                    printCharacter(c);
1251:                } else {
1252:                    char[] chars = new char[num];
1253:                    Arrays.fill(chars, c);
1254:                    printCharacters(chars);
1255:                }
1256:            }
1257:
1258:            /**
1259:             * Flush the console output stream. This is important for printout out
1260:             * single characters (like a backspace or keyboard) that we want the console
1261:             * to handle immedately.
1262:             */
1263:            public final void flushConsole() throws IOException {
1264:                out.flush();
1265:            }
1266:
1267:            private final int backspaceAll() throws IOException {
1268:                return backspace(Integer.MAX_VALUE);
1269:            }
1270:
1271:            /**
1272:             * Issue <em>num</em> backspaces.
1273:             *
1274:             * @return the number of characters backed up
1275:             */
1276:            private final int backspace(final int num) throws IOException {
1277:                if (buf.cursor == 0) {
1278:                    return 0;
1279:                }
1280:
1281:                int count = 0;
1282:
1283:                count = moveCursor(-1 * num) * -1;
1284:                // debug ("Deleting from " + buf.cursor + " for " + count);
1285:                buf.buffer.delete(buf.cursor, buf.cursor + count);
1286:                drawBuffer(count);
1287:
1288:                return count;
1289:            }
1290:
1291:            /**
1292:             * Issue a backspace.
1293:             *
1294:             * @return true if successful
1295:             */
1296:            public final boolean backspace() throws IOException {
1297:                return backspace(1) == 1;
1298:            }
1299:
1300:            private final boolean moveToEnd() throws IOException {
1301:                if (moveCursor(1) == 0) {
1302:                    return false;
1303:                }
1304:
1305:                while (moveCursor(1) != 0) {
1306:                    ;
1307:                }
1308:
1309:                return true;
1310:            }
1311:
1312:            /**
1313:             * Delete the character at the current position and redraw the remainder of
1314:             * the buffer.
1315:             */
1316:            private final boolean deleteCurrentCharacter() throws IOException {
1317:                boolean success = buf.buffer.length() > 0;
1318:                if (!success) {
1319:                    return false;
1320:                }
1321:
1322:                if (buf.cursor == buf.buffer.length()) {
1323:                    return false;
1324:                }
1325:
1326:                buf.buffer.deleteCharAt(buf.cursor);
1327:                drawBuffer(1);
1328:                return true;
1329:            }
1330:
1331:            private final boolean previousWord() throws IOException {
1332:                while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
1333:                    ;
1334:                }
1335:
1336:                while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) {
1337:                    ;
1338:                }
1339:
1340:                return true;
1341:            }
1342:
1343:            private final boolean nextWord() throws IOException {
1344:                while (isDelimiter(buf.current()) && (moveCursor(1) != 0)) {
1345:                    ;
1346:                }
1347:
1348:                while (!isDelimiter(buf.current()) && (moveCursor(1) != 0)) {
1349:                    ;
1350:                }
1351:
1352:                return true;
1353:            }
1354:
1355:            private final boolean deletePreviousWord() throws IOException {
1356:                while (isDelimiter(buf.current()) && backspace()) {
1357:                    ;
1358:                }
1359:
1360:                while (!isDelimiter(buf.current()) && backspace()) {
1361:                    ;
1362:                }
1363:
1364:                return true;
1365:            }
1366:
1367:            /**
1368:             * Move the cursor <i>where</i> characters.
1369:             *
1370:             * @param where
1371:             *            if less than 0, move abs(<i>where</i>) to the left,
1372:             *            otherwise move <i>where</i> to the right.
1373:             *
1374:             * @return the number of spaces we moved
1375:             */
1376:            public final int moveCursor(final int num) throws IOException {
1377:                int where = num;
1378:
1379:                if ((buf.cursor == 0) && (where < 0)) {
1380:                    return 0;
1381:                }
1382:
1383:                if ((buf.cursor == buf.buffer.length()) && (where > 0)) {
1384:                    return 0;
1385:                }
1386:
1387:                if ((buf.cursor + where) < 0) {
1388:                    where = -buf.cursor;
1389:                } else if ((buf.cursor + where) > buf.buffer.length()) {
1390:                    where = buf.buffer.length() - buf.cursor;
1391:                }
1392:
1393:                moveInternal(where);
1394:
1395:                return where;
1396:            }
1397:
1398:            /**
1399:             * debug.
1400:             *
1401:             * @param str
1402:             *            the message to issue.
1403:             */
1404:            public static void debug(final String str) {
1405:                if (debugger != null) {
1406:                    debugger.println(str);
1407:                    debugger.flush();
1408:                }
1409:            }
1410:
1411:            /**
1412:             * Move the cursor <i>where</i> characters, withough checking the current
1413:             * buffer.
1414:             *
1415:             * @see #where
1416:             *
1417:             * @param where
1418:             *            the number of characters to move to the right or left.
1419:             */
1420:            private final void moveInternal(final int where) throws IOException {
1421:                // debug ("move cursor " + where + " ("
1422:                // + buf.cursor + " => " + (buf.cursor + where) + ")");
1423:                buf.cursor += where;
1424:
1425:                char c;
1426:
1427:                if (where < 0) {
1428:                    int len = 0;
1429:                    for (int i = buf.cursor; i < buf.cursor - where; i++) {
1430:                        if (buf.getBuffer().charAt(i) == '\t')
1431:                            len += TAB_WIDTH;
1432:                        else
1433:                            len++;
1434:                    }
1435:
1436:                    char cbuf[] = new char[len];
1437:                    Arrays.fill(cbuf, BACKSPACE);
1438:                    out.write(cbuf);
1439:
1440:                    return;
1441:                } else if (buf.cursor == 0) {
1442:                    return;
1443:                } else if (mask != null) {
1444:                    c = mask.charValue();
1445:                } else {
1446:                    printCharacters(buf.buffer.substring(buf.cursor - where,
1447:                            buf.cursor).toCharArray());
1448:                    return;
1449:                }
1450:
1451:                // null character mask: don't output anything
1452:                if (NULL_MASK.equals(mask)) {
1453:                    return;
1454:                }
1455:
1456:                printCharacters(c, Math.abs(where));
1457:            }
1458:
1459:            /**
1460:             * Read a character from the console.
1461:             *
1462:             * @return the character, or -1 if an EOF is received.
1463:             */
1464:            public final int readVirtualKey() throws IOException {
1465:                int c = terminal.readVirtualKey(in);
1466:
1467:                if (debugger != null) {
1468:                    debug("keystroke: " + c + "");
1469:                }
1470:
1471:                // clear any echo characters
1472:                clearEcho(c);
1473:
1474:                return c;
1475:            }
1476:
1477:            public final int readCharacter(final char[] allowed)
1478:                    throws IOException {
1479:                // if we restrict to a limited set and the current character
1480:                // is not in the set, then try again.
1481:                char c;
1482:
1483:                Arrays.sort(allowed); // always need to sort before binarySearch
1484:
1485:                while (Arrays
1486:                        .binarySearch(allowed, c = (char) readVirtualKey()) < 0)
1487:                    ;
1488:
1489:                return c;
1490:            }
1491:
1492:            /**
1493:             *  Issue <em>num</em> deletes.
1494:             *
1495:             *  @return  the number of characters backed up
1496:             */
1497:            private final int delete(final int num) throws IOException {
1498:                /* Commented out beacuse of DWA-2949:
1499:                   if (buf.cursor == 0)
1500:                               return 0;*/
1501:
1502:                buf.buffer.delete(buf.cursor, buf.cursor + 1);
1503:                drawBuffer(1);
1504:
1505:                return 1;
1506:            }
1507:
1508:            public final boolean replace(int num, String replacement) {
1509:                buf.buffer.replace(buf.cursor - num, buf.cursor, replacement);
1510:                try {
1511:                    moveCursor(-num);
1512:                    drawBuffer(Math.max(0, num - replacement.length()));
1513:                    moveCursor(replacement.length());
1514:                } catch (IOException e) {
1515:                    e.printStackTrace();
1516:                    return false;
1517:                }
1518:                return true;
1519:            }
1520:
1521:            /**
1522:             *  Issue a delete.
1523:             *
1524:             *  @return  true if successful
1525:             */
1526:            public final boolean delete() throws IOException {
1527:                return delete(1) == 1;
1528:            }
1529:
1530:            public void setHistory(final History history) {
1531:                this .history = history;
1532:            }
1533:
1534:            public History getHistory() {
1535:                return this .history;
1536:            }
1537:
1538:            public void setCompletionHandler(
1539:                    final CompletionHandler completionHandler) {
1540:                this .completionHandler = completionHandler;
1541:            }
1542:
1543:            public CompletionHandler getCompletionHandler() {
1544:                return this .completionHandler;
1545:            }
1546:
1547:            /**
1548:             * <p>
1549:             * Set the echo character. For example, to have "*" entered when a password
1550:             * is typed:
1551:             * </p>
1552:             *
1553:             * <pre>
1554:             * myConsoleReader.setEchoCharacter(new Character('*'));
1555:             * </pre>
1556:             *
1557:             * <p>
1558:             * Setting the character to
1559:             *
1560:             * <pre>
1561:             * null
1562:             * </pre>
1563:             *
1564:             * will restore normal character echoing. Setting the character to
1565:             *
1566:             * <pre>
1567:             * new Character(0)
1568:             * </pre>
1569:             *
1570:             * will cause nothing to be echoed.
1571:             * </p>
1572:             *
1573:             * @param echoCharacter
1574:             *            the character to echo to the console in place of the typed
1575:             *            character.
1576:             */
1577:            public void setEchoCharacter(final Character echoCharacter) {
1578:                this .echoCharacter = echoCharacter;
1579:            }
1580:
1581:            /**
1582:             * Returns the echo character.
1583:             */
1584:            public Character getEchoCharacter() {
1585:                return this .echoCharacter;
1586:            }
1587:
1588:            /**
1589:             * No-op for exceptions we want to silently consume.
1590:             */
1591:            private void consumeException(final Throwable e) {
1592:            }
1593:
1594:            /**
1595:             * Checks to see if the specified character is a delimiter. We consider a
1596:             * character a delimiter if it is anything but a letter or digit.
1597:             *
1598:             * @param c
1599:             *            the character to test
1600:             * @return true if it is a delimiter
1601:             */
1602:            private boolean isDelimiter(char c) {
1603:                return !Character.isLetterOrDigit(c);
1604:            }
1605:
1606:            /**
1607:             * Whether or not to add new commands to the history buffer.
1608:             */
1609:            public void setUseHistory(boolean useHistory) {
1610:                this .useHistory = useHistory;
1611:            }
1612:
1613:            /**
1614:             * Whether or not to add new commands to the history buffer.
1615:             */
1616:            public boolean getUseHistory() {
1617:                return useHistory;
1618:            }
1619:
1620:            /**
1621:             * Whether to use pagination when the number of rows of candidates exceeds
1622:             * the height of the temrinal.
1623:             */
1624:            public void setUsePagination(boolean usePagination) {
1625:                this .usePagination = usePagination;
1626:            }
1627:
1628:            /**
1629:             * Whether to use pagination when the number of rows of candidates exceeds
1630:             * the height of the temrinal.
1631:             */
1632:            public boolean getUsePagination() {
1633:                return this.usePagination;
1634:            }
1635:
1636:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.