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

Reply via email to