001/* 002 * (C) Copyright 2006-2010 Nuxeo SAS (http://nuxeo.com/) and contributors. 003 * 004 * All rights reserved. This program and the accompanying materials 005 * are made available under the terms of the GNU Lesser General Public License 006 * (LGPL) version 2.1 which accompanies this distribution, and is available at 007 * http://www.gnu.org/licenses/lgpl.html 008 * 009 * This library is distributed in the hope that it will be useful, 010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 012 * Lesser General Public License for more details. 013 * 014 * Contributors: 015 * bstefanescu 016 */ 017package org.nuxeo.shell.swing; 018 019import javax.swing.text.BadLocationException; 020 021/** 022 * The last line in the console - where the user type the commands. Must be instantiated each time a new line is used. 023 * (after CRLF) 024 * 025 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a> 026 */ 027public class CmdLine { 028 029 protected int index; 030 031 protected int start; 032 033 protected String prompt; 034 035 protected int cmdStart; 036 037 protected Console console; 038 039 public CmdLine(Console console) { 040 try { 041 this.console = console; 042 this.index = console.getLineCount() - 1; 043 start = console.getLineStartOffset(index); 044 prompt = console.reader.getDefaultPrompt(); 045 cmdStart = start + prompt.length(); 046 } catch (Exception e) { 047 throw new RuntimeException(e); 048 } 049 } 050 051 public int getIndex() { 052 return index; 053 } 054 055 public int getStart() { 056 return start; 057 } 058 059 public int getCmdStart() { 060 return cmdStart; 061 } 062 063 public int getEnd() { 064 try { 065 return console.getLineEndOffset(index); 066 } catch (BadLocationException e) { 067 throw new RuntimeException(e); 068 } 069 } 070 071 public String getLineText() { 072 try { 073 return console.getDocument().getText(start, getEnd() - start); 074 } catch (BadLocationException e) { 075 throw new RuntimeException(e); 076 } 077 } 078 079 public String getPrompt() { 080 return prompt; 081 } 082 083 /** 084 * Get the caret position relative to the beginning of the command text (see getCmdStart()) 085 * 086 * @return 087 */ 088 public int getLocalCaretPosition() { 089 int cp = console.getCaretPosition() - cmdStart; 090 return cp < 0 ? 0 : cp; 091 } 092 093 public String getText() { 094 try { 095 return console.getDocument().getText(cmdStart, getEnd() - cmdStart); 096 } catch (BadLocationException e) { 097 throw new RuntimeException("Failed to get line text", e); 098 } 099 } 100 101 public void setText(String text) { 102 int end = getEnd(); 103 console.replaceRange(text, cmdStart, end); 104 console.setCaretPosition(console.getDocument().getLength()); 105 } 106 107 public void setTextFromCaret(String text) { 108 int end = getEnd(); 109 console.replaceRange(text, console.getCaretPosition(), end); 110 console.setCaretPosition(end); 111 } 112 113 public void write(String text) { 114 int cp = console.getCaretPosition(); 115 int end = getEnd(); 116 int len = text.length(); 117 if (cp < end) { 118 int e = cp + len; 119 if (e > end) { 120 console.replaceRange(text, cp, end); 121 } else { 122 console.replaceRange(text, cp, e); 123 } 124 } else { 125 console.insert(text, cp); 126 } 127 console.setCaretPosition(cp + len); 128 // console.repaint(); 129 } 130 131 public void sync() { 132 StringBuffer sb = console.reader.getCursorBuffer().getBuffer(); 133 sb.setLength(0); 134 sb.append(getText()); 135 console.reader.getCursorBuffer().cursor = getLocalCaretPosition(); 136 } 137 138 public void rsync() { 139 setText(console.reader.getCursorBuffer().getBuffer().toString()); 140 console.setCaretPosition(cmdStart + console.reader.getCursorBuffer().cursor); 141 } 142 143 public boolean canMoveCaret(int where) { 144 int cp = console.getCaretPosition() + where; 145 return cp >= cmdStart && cp <= getEnd(); 146 } 147 148 public int setCompletionWord(String word) { 149 int p = getLocalCaretPosition(); 150 String text = getText(); 151 Word w = getWord(text, p); 152 // replace w with word 153 int ws = cmdStart + w.index; 154 int we = ws + w.length(); 155 console.replaceRange(word, ws, we); 156 console.setCaretPosition(ws + word.length()); 157 return getLocalCaretPosition(); 158 } 159 160 /** 161 * Get the word from the command line which is near the given relative caret position. Used for completion. 162 * 163 * @param pos 164 * @return 165 */ 166 public Word getWord(String text, int pos) { 167 if (text.length() == 0) { 168 return new Word("", 0); 169 } 170 if (pos <= 0) { 171 // get next word 172 int i = text.indexOf(' '); 173 String w = i <= 0 ? "" : text.substring(0, i); 174 return new Word(w, 0); 175 } 176 // get the previous word. 177 int i = text.lastIndexOf(' ', pos); 178 if (i == -1) { 179 i = 0; 180 int e = text.indexOf(' '); 181 if (e == -1) { 182 return new Word(text, 0); 183 } else { 184 return new Word(text.substring(0, e), 0); 185 } 186 } else { 187 i++; 188 int e = text.indexOf(' ', i); 189 if (e == -1) { 190 return new Word(text.substring(i), i); 191 } else { 192 return new Word(text.substring(i, e), i); 193 } 194 } 195 } 196 197 static class Word { 198 public int index; 199 200 public String text; 201 202 public Word(String text, int index) { 203 this.text = text; 204 this.index = index; 205 } 206 207 public int length() { 208 return text.length(); 209 } 210 211 @Override 212 public String toString() { 213 return text + " [" + index + "]"; 214 } 215 } 216}