Revision: 5368 http://jnode.svn.sourceforge.net/jnode/?rev=5368&view=rev Author: chrisboertien Date: 2009-04-30 03:13:37 +0000 (Thu, 30 Apr 2009)
Log Message: ----------- Implemented -n/-b/-s/-E flags for cat Signed-off-by: chrisboertien <chris.boert...@gmail.com> Modified Paths: -------------- trunk/cli/descriptors/org.jnode.command.file.xml trunk/cli/src/commands/org/jnode/command/file/CatCommand.java Modified: trunk/cli/descriptors/org.jnode.command.file.xml =================================================================== --- trunk/cli/descriptors/org.jnode.command.file.xml 2009-04-29 22:41:40 UTC (rev 5367) +++ trunk/cli/descriptors/org.jnode.command.file.xml 2009-04-30 03:13:37 UTC (rev 5368) @@ -43,21 +43,28 @@ <alias name="tail" class="org.jnode.command.file.TailCommand"/> <alias name="touch" class="org.jnode.command.file.TouchCommand"/> <alias name="wc" class="org.jnode.command.file.WcCommand"/> - <!-- can't find org.jnode.command.file.WcCommand --> </extension> <extension point="org.jnode.shell.syntaxes"> <syntax alias="cat"> <empty description="copy standard input to standard output"/> + <sequence description="concatenate files to standard output"> + <optionSet> + <option argLabel="num-nonblank" shortName="b" longName="number-nonblank"/> + <option argLabel="num" shortName="n" longName="number"/> + <option argLabel="squeeze" shortName="s" longName="sqeeze-blank"/> + <option argLabel="show-ends" shortName="E" longName="show-ends"/> + </optionSet> + <repeat minCount="1"> + <argument argLabel="file"/> + </repeat> + </sequence> <sequence description="fetch and concatenate urls to standard output"> <option argLabel="urls" shortName="u" longName="urls"/> <repeat minCount="1"> <argument argLabel="url"/> </repeat> </sequence> - <repeat minCount="1" description="concatenate files to standard output"> - <argument argLabel="file"/> - </repeat> </syntax> <syntax alias="cd"> <empty description="change the current directory to the 'user.home' directory"/> @@ -105,7 +112,7 @@ <argument argLabel="directory" description="directory to start printing sizes recursively"/> </repeat> <optionSet> - <option argLabel="sum" shortName="s" longName="summarize"/> + <option argLabel="sum" shortName="s" longName="summarize"/> <option argLabel="all" shortName="a" longName="all"/> <option argLabel="human-readable" shortName="h" longName="human-readable"/> </optionSet> Modified: trunk/cli/src/commands/org/jnode/command/file/CatCommand.java =================================================================== --- trunk/cli/src/commands/org/jnode/command/file/CatCommand.java 2009-04-29 22:41:40 UTC (rev 5367) +++ trunk/cli/src/commands/org/jnode/command/file/CatCommand.java 2009-04-30 03:13:37 UTC (rev 5368) @@ -20,15 +20,18 @@ package org.jnode.command.file; +import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; import java.io.FileNotFoundException; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; +import java.io.Reader; import java.net.URL; +import org.jnode.command.util.IOUtils; import org.jnode.shell.AbstractCommand; import org.jnode.shell.syntax.Argument; import org.jnode.shell.syntax.FileArgument; @@ -53,115 +56,240 @@ private static final String help_file = "the files to be concatenated"; private static final String help_url = "the urls to be concatenated"; private static final String help_urls = "If set, arguments will be urls"; + private static final String help_num_nb = "If set, number nonempty output lines"; + private static final String help_num = "If set, number all output lines"; + private static final String help_ends = "If set, print a $ at the end of each lines"; + private static final String help_squeeze = "If set, supress printing of sequential blank lines"; private static final String help_super = "Concatenate the contents of files, urls or standard input"; private static final String err_url = "Cannot fetch %s: %s%n"; - private static final String err_file = "Cannot open %s: %s%n"; + private static final String err_file = "Cannot open %sn"; private final FileArgument argFile; + private final FlagArgument argNumNB; + private final FlagArgument argNumAll; + private final FlagArgument argEnds; + private final FlagArgument argSqueeze; + private final URLArgument argUrl; private final FlagArgument argUrls; private PrintWriter err; + private PrintWriter out; + private Reader in; + private InputStream stdin; + private OutputStream stdout; + private File[] files; + private String end; + private int rc = 0; + private boolean squeeze; + private boolean numAll; + private boolean numNB; + private boolean useStreams; public CatCommand() { super(help_super); - argFile = new FileArgument("file", Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, help_file); - argUrl = new URLArgument("url", Argument.OPTIONAL | Argument.MULTIPLE | Argument.EXISTING, help_url); + int fileFlags = Argument.MULTIPLE | Argument.EXISTING | FileArgument.HYPHEN_IS_SPECIAL; + argFile = new FileArgument("file", fileFlags, help_file); + argNumNB = new FlagArgument("num-nonblank", 0, help_num_nb); + argNumAll = new FlagArgument("num", 0, help_num); + argEnds = new FlagArgument("show-ends", 0, help_ends); + argSqueeze = new FlagArgument("squeeze", 0, help_squeeze); + registerArguments(argFile, argNumNB, argNumAll, argEnds, argSqueeze); + + argUrl = new URLArgument("url", Argument.MULTIPLE | Argument.EXISTING, help_url); argUrls = new FlagArgument("urls", Argument.OPTIONAL, help_urls); - registerArguments(argFile, argUrl, argUrls); + registerArguments(argUrl, argUrls); } - + private static final int BUFFER_SIZE = 8192; - - + public static void main(String[] args) throws Exception { new CatCommand().execute(args); } public void execute() throws IOException { - this.err = getError().getPrintWriter(); - OutputStream out = getOutput().getOutputStream(); - File[] files = argFile.getValues(); - URL[] urls = argUrl.getValues(); + in = getInput().getReader(); + stdin = getInput().getInputStream(); + out = getOutput().getPrintWriter(); + stdout = getOutput().getOutputStream(); + err = getError().getPrintWriter(); - boolean ok = true; + parseOptions(); + + if (files != null && files.length > 0) { + handleFiles(); + out.flush(); + exit(rc); + } + + // FIXME remove this url code once wget is more complete + URL[] urls = argUrl.getValues(); if (urls != null && urls.length > 0) { + byte[] buffer = new byte[BUFFER_SIZE]; for (URL url : urls) { InputStream is = null; try { is = url.openStream(); } catch (IOException ex) { err.format(err_url, url, ex.getLocalizedMessage()); - ok = false; + rc = 1; } if (is != null) { try { - process(is, out); + IOUtils.copyStream(is, stdout, buffer); } finally { - try { - is.close(); - } catch (IOException ex) { - /* ignore */ - } + IOUtils.close(is); } } } - } else if (files != null && files.length > 0) { - for (File file : files) { - InputStream is = null; - try { - is = openFile(file); - if (is == null) { - ok = false; + out.flush(); + exit(rc); + } + + // should not reach this + throw new IllegalStateException("Nothing to process"); + } + + private boolean handleFiles() { + InputStream in = null; + BufferedReader reader = null; + byte[] buffer = new byte[BUFFER_SIZE]; + boolean ok = true; + + for (File file : files) { + try { + if (useStreams) { + if ((in = openFileStream(file)) != null) { + IOUtils.copyStream(in, stdout, buffer); } else { - process(is, out); + rc = 1; } - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException ex) { - /* ignore */ - } + } else { + if ((reader = openFileReader(file)) != null) { + processReader(reader); + } else { + rc = 1; } } + } catch (IOException e) { + rc = 1; + } finally { + IOUtils.close(in, reader); } - } else { - process(getInput().getInputStream(), out); } - out.flush(); - if (!ok) { - exit(1); - } + + return ok; } - + /** - * Copy all of stream 'in' to stream 'out' - * @param in - * @param out - * @throws IOException + * Process the input through a BufferedReader. + * + * Instead of doing a straight stream->stream copy, we process line by line + * in order to do some per-line editing before we send to stdout. */ - private void process(InputStream in, OutputStream out) throws IOException { - int len; - final byte[] buf = new byte[BUFFER_SIZE]; - while ((len = in.read(buf)) > 0) { - out.write(buf, 0, len); + private void processReader(BufferedReader reader) throws IOException { + String line; + boolean haveBlank = false; + int lineCount = 0; + + while ((line = reader.readLine()) != null) { + if (line.length() == 0) { + if (!haveBlank) { + haveBlank = true; + } else if (squeeze) { + continue; + } + } else { + haveBlank = false; + } + + if (numAll) { + println(line, ++lineCount); + } else if (numNB) { + println(line, (haveBlank ? -1 : ++lineCount)); + } else { + println(line, 0); + } } } /** - * Attempt to open a file, writing an error message on failure. + * Attempt to open a file, writing an error message on failure. If the file + * is '-', return stdin. + * * @param fname the filename of the file to be opened * @return An open stream, or <code>null</code>. - * @throws FileNotFoundException */ - private InputStream openFile(File file) throws FileNotFoundException { - try { - return new FileInputStream(file); - } catch (IOException ex) { - err.format(err_file, file, ex.getLocalizedMessage()); - return null; + private InputStream openFileStream(File file) { + InputStream ret = null; + + if (file.getName().equals("-")) { + ret = stdin; + } else { + ret = IOUtils.openInputStream(file, true, BUFFER_SIZE); + if (ret == null) { + err.format(err_file, file); + } } + + return ret; } - + + private BufferedReader openFileReader(File file) { + BufferedReader ret = null; + + if (file.getName().equals("-")) { + ret = new BufferedReader(in, BUFFER_SIZE); + } else { + try { + ret = new BufferedReader(new FileReader(file), BUFFER_SIZE); + } catch (FileNotFoundException e) { + err.format(err_file, file); + } + } + + return ret; + } + + private void parseOptions() { + files = argFile.getValues(); + + if (files == null || files.length == 0) { + files = new File[] {new File("-")}; + } + + useStreams = true; + + if (argNumNB.isSet()) { + numNB = true; + useStreams = false; + } else if (argNumAll.isSet()) { + numAll = true; + useStreams = false; + } + + if (argEnds.isSet()) { + end = "$"; + useStreams = false; + } else { + end = ""; + } + + if (argSqueeze.isSet()) { + squeeze = true; + useStreams = false; + } + } + + private void println(String s, int line) { + if (numNB || numAll) { + if (line == -1) { + out.format(" %s%s%n", s, end); + } else { + out.format("%6d %s%s%n", line, s, end); + } + } else { + out.format("%s%s%n", s, end); + } + } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------------ Register Now & Save for Velocity, the Web Performance & Operations Conference from O'Reilly Media. Velocity features a full day of expert-led, hands-on workshops and two days of sessions from industry leaders in dedicated Performance & Operations tracks. Use code vel09scf and Save an extra 15% before 5/3. http://p.sf.net/sfu/velocityconf _______________________________________________ Jnode-svn-commits mailing list Jnode-svn-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/jnode-svn-commits