"$System.in"
で入力が取れる仕組みを今更ながら追ってみた。
// groovy-1.5.7/src/main/groovy/lang/GString.java 148-157 public String toString() { StringWriter buffer = new StringWriter(); try { writeTo(buffer); } catch (IOException e) { throw new StringWriterIOException(e); } return buffer.toString(); }
- toString は writeTo を使用。
// groovy-1.5.7/src/main/groovy/lang/GString.java 159-184 public Writer writeTo(Writer out) throws IOException { String[] s = getStrings(); int numberOfValues = values.length; for (int i = 0, size = s.length; i < size; i++) { out.write(s[i]); if (i < numberOfValues) { final Object value = values[i]; if (value instanceof Closure) { final Closure c = (Closure)value; if (c.getMaximumNumberOfParameters() == 0) { InvokerHelper.write(out, c.call(null)); } else if (c.getMaximumNumberOfParameters() == 1) { c.call(new Object[]{out}); } else { throw new GroovyRuntimeException("Trying to evaluate a GString containing a Closure taking " + c.getMaximumNumberOfParameters() + " parameters"); } } else { InvokerHelper.write(out, value); } } } return out; }
// groovy-1.5.7/src/main/org/codehaus/groovy/runtime/InvokerHelper.java 474-503 public static void write(Writer out, Object object) throws IOException { if (object instanceof String) { out.write((String) object); } else if (object instanceof Object[]) { out.write(toArrayString((Object[]) object)); } else if (object instanceof Map) { out.write(toMapString((Map) object)); } else if (object instanceof Collection) { out.write(toListString((Collection) object)); } else if (object instanceof Writable) { Writable writable = (Writable) object; writable.writeTo(out); } else if (object instanceof InputStream || object instanceof Reader) { // Copy stream to stream Reader reader; if (object instanceof InputStream) { reader = new InputStreamReader((InputStream) object); } else { reader = (Reader) object; } char[] chars = new char[8192]; int i; while ((i = reader.read(chars)) != -1) { out.write(chars, 0, i); } reader.close(); } else { out.write(toString(object)); } }
- InputStream と Reader に対応している。読んで書いて閉じる*1。
- Writable なら 書かせるだけ。
def c = { it << 'hoge' } def w = [writeTo: c] as Writable; assert "$c $w" == 'hoge hoge'
*1:このため「"$System.in"」は再利用が効かず,二回以上使う場合は「System.in.text」で妥協する。