Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  package org.jruby.demo;
  
  import java.awt.Color;
  import java.awt.Point;
 import java.util.List;
 
 import org.jruby.Ruby;
 
 public class TextAreaReadline implements KeyListener {
     private static final String EMPTY_LINE = "";
     
     private JTextComponent area;
     private volatile int startPos;
     private String currentLine;
     
     public volatile MutableAttributeSet promptStyle;
     public volatile MutableAttributeSet inputStyle;
     public volatile MutableAttributeSet outputStyle;
     public volatile MutableAttributeSet resultStyle;
     
     private JComboBox completeCombo;
     private BasicComboPopup completePopup;
     private int start;
     private int end;
 
     private final InputStream inputStream = new Input();
     private final OutputStream outputStream = new Output();
 
     private static class InputBuffer {
         public final byte[] bytes;
         public int offset = 0;
         public InputBuffer(byte[] bytes) {
             this. = bytes;
         }
     }
 
     public enum Channel {
         AVAILABLE,
         READ,
         BUFFER,
         EMPTY,
         LINE,
         GET_LINE,
         SHUTDOWN,
         FINISHED
     }
 
     private static class ReadRequest {
         public final byte[] b;
         public final int off;
         public final int len;
 
         public ReadRequest(byte[] bint offint len) {
             this. = b;
             this. = off;
             this. = len;
         }
 
         public int perform(Join joinInputBuffer buffer) {
             final int available = buffer.bytes.length - buffer.offset;
             int len = this.;
             if ( len > available ) {
                 len = available;
             }
             if ( len == available ) {
                 join.send(.null);
             } else {
                 buffer.offset += len;
                 join.send(.buffer);
            }
            System.arraycopy(buffer.bytesbuffer.offsetthis.this.len);
            return len;
        }
    }
    private static final Join.Spec INPUT_SPEC = new Join.Spec() {{
            public void react(Join joinObject[] args) {
                join.send(.null);
            }
        });
            public void react(Join joinObject[] args) {
                join.send(.null);
            }
        });
            public void react(Join joinObject[] args) {
                join.send(.null);
            }
        });
            public void react(Join joinObject[] args) {
                join.send(.null);
            }
        });
            public Object react(Join joinObject[] args) {
                InputBuffer buffer = (InputBuffer)args[1];
                join.send(.buffer);
                return buffer.bytes.length - buffer.offset;
            }
        });
            public Object react(Join joinObject[] args) {
                join.send(.null);
                return 0;
            }
        });
            public Object react(Join joinObject[] args) {
                join.send(.null);
                return 0;
            }
        });
            public Object react(Join joinObject[] args) {
                return ((ReadRequest)args[0]).perform(join, (InputBuffer)args[1]);
            }
        });
            public Object react(Join joinObject[] args) {
                final ReadRequest request = (ReadRequest)args[0];
                final String line = (String)args[2];
                if (line.length() != 0) {
                    byte[] bytes = RubyEncoding.encodeUTF8(line);
                    return request.perform(joinnew InputBuffer(bytes));
                } else {
                    return -1;
                }
            }
        });
            public Object react(Join joinObject[] args) {
                join.send(.null);
                return -1;
            }
        });
            public Object react(Join joinObject[] args) {
                return args[1];
            }
        });
            public Object react(Join joinObject[] args) {
                join.send(.null);
                return ;
            }
        });
    }};
    private static final int MAX_DOC_SIZE = 100000;
    private final Join inputJoin = .createJoin();
    public TextAreaReadline(JTextComponent area) {
        this(areanull);
    }
    
    public TextAreaReadline(JTextComponent areafinal String message) {
        this. = area;
        .send(.null);
        
        area.addKeyListener(this);
        
        // No editing before startPos
        if (area.getDocument() instanceof AbstractDocument) {
            ((AbstractDocumentarea.getDocument()).setDocumentFilter(
                new DocumentFilter() {
                    public void insertString(DocumentFilter.FilterBypass fbint offsetString stringAttributeSet attrthrows BadLocationException {
                        if (offset >= super.insertString(fboffsetstringattr);
                    }
                    
                    public void remove(DocumentFilter.FilterBypass fbint offsetint lengththrows BadLocationException {
                        if (offset >=  || offset == 0) super.remove(fboffsetlength);
                    }
                    
                    public void replace(DocumentFilter.FilterBypass fbint offsetint lengthString textAttributeSet attrsthrows BadLocationException {
                        if (offset >= super.replace(fboffsetlengthtextattrs);
                    }
                }
            );
        }
        
         = new SimpleAttributeSet();
        StyleConstants.setForeground(new Color(0xa4, 0x00, 0x00));
        
         = new SimpleAttributeSet();
        StyleConstants.setForeground(new Color(0x20, 0x4a, 0x87));
        
         = new SimpleAttributeSet();
        StyleConstants.setForeground(.);
        
         = new SimpleAttributeSet();
        StyleConstants.setItalic(true);
        StyleConstants.setForeground(new Color(0x20, 0x4a, 0x87));
        
         = new JComboBox();
        .setRenderer(new DefaultListCellRenderer()); // no silly ticks!
        
        if (message != null) {
            final MutableAttributeSet messageStyle = new SimpleAttributeSet();
            StyleConstants.setBackground(messageStylearea.getForeground());
            StyleConstants.setForeground(messageStylearea.getBackground());
            append(messagemessageStyle);
        }
         = area.getDocument().getLength();
    }
    public InputStream getInputStream() {
        return ;
    }
    public OutputStream getOutputStream() {
        return ;
    }
    
    private Ruby runtime;

    
Hooks this TextAreaReadline instance into the runtime, redefining the Readline module so that it uses this object. This method does not redefine the standard input-output streams. If you need that, use hookIntoRuntimeWithStreams(org.jruby.Ruby).

Parameters:
runtime The runtime.
See also:
hookIntoRuntimeWithStreams(org.jruby.Ruby)
    public void hookIntoRuntime(final Ruby runtime) {
        this. = runtime;
        /* Hack in to replace usual readline with this */
        runtime.getLoadService().require("readline");
        RubyModule readlineM = runtime.getModule("Readline");
        readlineM.defineModuleFunction("readline"new Callback() {
            public IRubyObject execute(IRubyObject recvIRubyObject[] argsBlock block) {
                String line = readLine(args[0].toString());
                if (line != null) {
                    return RubyString.newUnicodeString(runtimeline);
                } else {
                    return runtime.getNil();
                }
            }
            public Arity getArity() { return Arity.twoArguments(); }
        });
    }

    
Hooks this TextAreaReadline instance into the runtime, redefining the Readline module so that it uses this object. This method also redefines the standard input-output streams accordingly.

Parameters:
runtime The runtime.
See also:
hookIntoRuntime(org.jruby.Ruby)
    public void hookIntoRuntimeWithStreams(final Ruby runtime) {
        hookIntoRuntime(runtime);
        RubyIO in = new RubyIO(runtimegetInputStream());
        runtime.getGlobalVariables().set("$stdin"in);
        RubyIO out = new RubyIO(runtimegetOutputStream());
        runtime.getGlobalVariables().set("$stdout"out);
        runtime.getGlobalVariables().set("$stderr"out);
    }
    
    protected void completeAction(KeyEvent event) {
        if (Readline.getCompletor(Readline.getHolder()) == nullreturn;
        
        event.consume();
        
        if (.isVisible()) return;
        
        List candidates = new LinkedList();
        String bufstr = null;
        try {
            bufstr = .getText(.getCaretPosition() - );
        } catch (BadLocationException e) {
            return;
        }
        
        int cursor = .getCaretPosition() - ;
        
        int position = Readline.getCompletor(Readline.getHolder()).complete(bufstrcursorcandidates);
        
        // no candidates? Fail.
        if (candidates.isEmpty()) {
            return;
        }
        
        if (candidates.size() == 1) {
            replaceText( + position.getCaretPosition(), (Stringcandidates.get(0));
            return;
        }
        
         =  + position;
         = .getCaretPosition();
        
        Point pos = .getCaret().getMagicCaretPosition();
        // bit risky if someone changes completor, but useful for method calls
        int cutoff = bufstr.substring(position).lastIndexOf('.') + 1;
         += cutoff;
        if (candidates.size() < 10) {
            .getList().setVisibleRowCount(candidates.size());
        } else {
            .getList().setVisibleRowCount(10);
        }
        .removeAllItems();
        for (Iterator i = candidates.iterator(); i.hasNext();) {
            String item = (Stringi.next();
            if (cutoff != 0) item = item.substring(cutoff);
            .addItem(item);
        }
        .show(pos.xpos.y + .getFontMetrics(.getFont()).getHeight());
    }
    protected void backAction(KeyEvent event) {
        if (.getCaretPosition() <= ) {
            event.consume();
        }
    }
    
    protected void upAction(KeyEvent event) {
        event.consume();
        
        if (.isVisible()) {
            int selected = .getSelectedIndex() - 1;
            if (selected < 0) return;
            .setSelectedIndex(selected);
            return;
        }
        
        if (!Readline.getHistory(Readline.getHolder()).next()) {
             = getLine(); // at end
        } else {
            Readline.getHistory(Readline.getHolder()).previous(); //undo check
        }
        
        if (!Readline.getHistory(Readline.getHolder()).previous()) return;
        
        String oldLine = Readline.getHistory(Readline.getHolder()).current().toString().trim();
        replaceText(.getDocument().getLength(), oldLine);
    }
    
    protected void downAction(KeyEvent event) {
        event.consume();
        
        if (.isVisible()) {
            int selected = .getSelectedIndex() + 1;
            if (selected == .getItemCount()) return;
            .setSelectedIndex(selected);
            return;
        }
        
        if (!Readline.getHistory(Readline.getHolder()).next()) return;
        
        String oldLine;
        if (!Readline.getHistory(Readline.getHolder()).next()) {
            oldLine = // at end
        } else {
            Readline.getHistory(Readline.getHolder()).previous(); // undo check
            oldLine = Readline.getHistory(Readline.getHolder()).current().toString().trim();
        }
        
        replaceText(.getDocument().getLength(), oldLine);
    }
    
    protected void replaceText(int startint endString replacement) {
        try {
            .getDocument().remove(startend - start);
            .getDocument().insertString(startreplacement);
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }
    
    protected String getLine() {
        try {
            return .getText(.getDocument().getLength() - );
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    protected void enterAction(KeyEvent event) {
        event.consume();
        
        if (.isVisible()) {
            if (.getSelectedItem() != null) {
                replaceText(, (String.getSelectedItem());
            }
            .setVisible(false);
            return;
        }
        
        append("\n"null);
        
        String line = getLine();
         = .getDocument().getLength();
        .send(.line);
    }
    
    public String readLine(final String prompt) {
        if (EventQueue.isDispatchThread()) {
            throw .newThreadError("Cannot call readline from event dispatch thread");
        }
        EventQueue.invokeLater(new Runnable() {
           public void run() {
               append(prompt.trim(), );
               append(" "); // hack to get right style for input
               .setCaretPosition(.getDocument().getLength());
                = .getDocument().getLength();
               Readline.getHistory(Readline.getHolder()).moveToEnd();
            }
        });
        
        final String line = (String).call(.null);
        if (line.length() > 0) {
            return line.trim();
        } else {
            return null;
        }
    }
    
    public void keyPressed(KeyEvent event) {
        int code = event.getKeyCode();
        switch (code) {
        case .completeAction(event); break;
        case .
        case .:
            backAction(event); break;
        case .upAction(event); break;
        case .downAction(event); break;
        case .enterAction(event); break;
        case .event.consume(); .setCaretPosition(); break;
        case .:
            if ( ( event.getModifiersEx() & . ) != 0 ) {
                event.consume();
                .send(.);
            }
            break;
        }
        
        if (.isVisible() &&
                code !=  . &&
                code != . &&
                code != . )
            .setVisible(false);
    }
    public void keyReleased(KeyEvent arg0) { }
    public void keyTyped(KeyEvent arg0) { }
    public void shutdown() {
        .send(.null);
    }

    
Output methods
    protected void append(String toAppendAttributeSet style) {
       try {
           Document doc = .getDocument();
           doc.insertString(doc.getLength(), toAppendstyle);
           // Cut the document to fit into the MAX_DOC_SIZE.
           // See JRUBY-4237.
           int extra = doc.getLength() - ;
           if (extra > 0) {
               int removeBytes = extra + /10;
               doc.remove(0, removeBytes);
                -= removeBytes;
           }
       } catch (BadLocationException e) {}
    }
    private void writeLineUnsafe(final String line) {
        if (line.startsWith("=>")) {
            append(line);
        } else {
            append(line);
        }
         = .getDocument().getLength();
    }
    
    private void writeLine(final String line) {
        if (EventQueue.isDispatchThread()) {
            writeLineUnsafe(line);
        } else {
            EventQueue.invokeLater(new Runnable() {
                public void run() {
                    writeLineUnsafe(line);
                }
            });
        }
    }
    private class Input extends InputStream {
        private volatile boolean closed = false;
        @Override
        public int available() throws IOException {
            if () {
                throw new IOException("Stream is closed");
            }
            return (Integer).call(.null);
        }
        @Override
        public int read() throws IOException {
            byte[] b = new byte[1];
            if ( read(b, 0, 1) == 1 ) {
                return b[0];
            } else {
                return -1;
            }
        }
        @Override
        public int read(byte[] bint offint lenthrows IOException {
            if () {
                throw new IOException("Stream is closed");
            }
            if (EventQueue.isDispatchThread()) {
                throw new IOException("Cannot call read from event dispatch thread");
            }
            if (b == null) {
                throw new NullPointerException();
            }
            if (off < 0 || len < 0 || off+len > b.length) {
                throw new IndexOutOfBoundsException();
            }
            if (len == 0) {
                return 0;
            }
            final ReadRequest request = new ReadRequest(bofflen);
            return (Integer).call(.request);
        }
        @Override
        public void close() {
             = true;
            .send(.null);
        }
    }
    private class Output extends OutputStream {
        @Override
        public void write(int bthrows IOException {
            writeLine("" + b);
        }
        @Override
        public void write(byte[] bint offint len) {
            writeLine(RubyEncoding.decodeUTF8(bofflen));
        }
        @Override
        public void write(byte[] b) {
            writeLine(RubyEncoding.decodeUTF8(b));
        }
    }
New to GrepCode? Check out our FAQ X