[SCM] master: Add log completer.

cagney@sourceware.org cagney@sourceware.org
Fri Dec 7 16:27:00 GMT 2007


The branch, master has been updated
       via  88f78bba64995ee006c9da8e22f655b4a6ad57c4 (commit)
      from  1428e86f7a48aceaee478725a9a8c641d502f7db (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email.

- Log -----------------------------------------------------------------
commit 88f78bba64995ee006c9da8e22f655b4a6ad57c4
Author: Andrew Cagney <cagney@redhat.com>
Date:   Fri Dec 7 11:26:32 2007 -0500

    Add log completer.
    
    frysk-sys/frysk/rsl/ChangeLog
    2007-12-07  Andrew Cagney  <cagney@redhat.com>
    
    	* TestLog.java (testCompletion()): New.
    	(checkComplete(String,int,String[])): New.
    	(testName()): New.
    	(testPath()): New.
    	(testCompleteChildPresent()): New.
    	(testCompleteChildMissing()): New.
    	(testCompleteSingle()): New.
    	(testCompleteSingle()): New.
    	(testCompleteMultiple()): New.
    	(testCompleteMidway()): New.
    	(testCompleteNothing()): New.
    	(testCompleteBogus()): New.
    	* Log.java (Log(String,String,Log)): Add Second string name
    	parameter.
    	(name()): New.
    	(path()): New.
    	(complete(String,List)): New.
    	(complete(String,int,List)): New.
    	(children): Change type to TreeMap.

-----------------------------------------------------------------------

Summary of changes:
 frysk-common/Makefile.gen.sh     |    4 +-
 frysk-sys/frysk/rsl/ChangeLog    |   22 ++++++++
 frysk-sys/frysk/rsl/Log.java     |  110 ++++++++++++++++++++++++++++++++++++--
 frysk-sys/frysk/rsl/TestLog.java |   56 +++++++++++++++++++-
 4 files changed, 183 insertions(+), 9 deletions(-)

First 500 lines of diff:
diff --git a/frysk-common/Makefile.gen.sh b/frysk-common/Makefile.gen.sh
index fc374d8..21a4a1f 100755
--- a/frysk-common/Makefile.gen.sh
+++ b/frysk-common/Makefile.gen.sh
@@ -569,9 +569,7 @@ else
 fi
 
 # Grep the cni/*.cxx files forming a list of included files.  Assume
-# these are all generated from .class files.  The list can be pruned a
-# little since, given Class$Nested and Class, generating Class.h will
-# automatically generate the inner Class$Nested class.
+# these are all generated from .class files found in the master .jar.
 
 # This matches both:
 # #include "a/file/dot.h"
diff --git a/frysk-sys/frysk/rsl/ChangeLog b/frysk-sys/frysk/rsl/ChangeLog
index 48622a0..a7f1335 100644
--- a/frysk-sys/frysk/rsl/ChangeLog
+++ b/frysk-sys/frysk/rsl/ChangeLog
@@ -1,3 +1,25 @@
+2007-12-07  Andrew Cagney  <cagney@redhat.com>
+
+	* TestLog.java (testCompletion()): New.
+	(checkComplete(String,int,String[])): New.
+	(testName()): New.
+	(testPath()): New.
+	(testCompleteChildPresent()): New.
+	(testCompleteChildMissing()): New.
+	(testCompleteSingle()): New.
+	(testCompleteSingle()): New.
+	(testCompleteMultiple()): New.
+	(testCompleteMidway()): New.
+	(testCompleteNothing()): New.
+	(testCompleteBogus()): New.
+	* Log.java (Log(String,String,Log)): Add Second string name
+	parameter.
+	(name()): New.
+	(path()): New.
+	(complete(String,List)): New.
+	(complete(String,int,List)): New.
+	(children): Change type to TreeMap.
+
 2007-12-06  Andrew Cagney  <cagney@redhat.com>
 
 	New directory.
diff --git a/frysk-sys/frysk/rsl/Log.java b/frysk-sys/frysk/rsl/Log.java
index 9bbfcdf..964f919 100644
--- a/frysk-sys/frysk/rsl/Log.java
+++ b/frysk-sys/frysk/rsl/Log.java
@@ -40,8 +40,9 @@
 package frysk.rsl;
 
 import java.io.PrintStream;
-import java.util.HashMap;
+import java.util.TreeMap;
 import java.util.Iterator;
+import java.util.List;
 
 /**
  * Generate log information when enabled.
@@ -50,10 +51,13 @@ public final class Log {
 
     private int level;
     private final String path;
-    private Log(String path, Log parent) {
+    private final String name;
+    private Log(String path, String name, Log parent) {
 	this.path = path;
 	this.level = parent.level;
+	this.name = name;
     }
+
     /**
      * Create a root logger; package private so that test code can
      * create their own root logger.
@@ -61,6 +65,7 @@ public final class Log {
     Log() {
 	this.level = 0;
 	this.path = "";
+	this.name = "";
     }
 
     public String toString() {
@@ -70,7 +75,23 @@ public final class Log {
 		+ "}");
     }
 
-    private final HashMap children = new HashMap();
+    /**
+     * Return the "basename" of the logger.
+     */
+    public final String name() {
+	return name;
+    }
+    /**
+     * Return the full path of the logger.
+     */
+    public final String path() {
+	return path;
+    }
+
+    private final TreeMap children = new TreeMap();
+    /**
+     * Set this logger's logging level.
+     */
     public synchronized final Log set(Level level) {
 	this.level = level.intValue();
 	for (Iterator i = children.values().iterator(); i.hasNext(); ) {
@@ -79,12 +100,16 @@ public final class Log {
 	}
 	return this;
     }
-    public Level level() {
+    /**
+     * Return this loggers current logging level.
+     */
+    public final Level level() {
 	return Level.valueOf(level);
     }
 
     /**
      * POS starts at -1, then points at "." or the end of the name.
+     * Package private so it can be called from test code.
      */
     synchronized final Log get(String path, int pos) {
 	if (pos >= path.length())
@@ -97,20 +122,95 @@ public final class Log {
 	String name = path.substring(pos + 1, dot);
 	Log child = (Log)children.get(name);
 	if (child == null) {
-	    child = new Log(path.substring(0, dot), this);
+	    child = new Log(path.substring(0, dot), name, this);
 	    children.put(name, child);
 	}
 	return child.get(path, dot);
     }
 
     private static final Log root = new Log();
+    /**
+     * Find the logger by the name KLASS.
+     */
     public static Log get(String klass) {
 	return root.get(klass, -1);
     }
+    /**
+     * Find the logger by with KLASS's name.
+     */
     public static Log get(Class klass) {
 	return root.get(klass.getName(), -1);
     }
 
+    /**
+     * Complete the logger.  On entry, POS is either -1 or the
+     * location of the last DOT indicating further name completion is
+     * needed; or the length indicating that either a "." or " "
+     * completion is needed.
+     *
+     * Returns the offset into INCOMPLETE that the completions apply
+     * to, or -1.
+     *
+     * Package private to allow testing.
+     */
+    synchronized final int complete(String incomplete, int pos,
+				    List candidates) {
+	int dot = incomplete.indexOf('.', pos + 1);
+	if (dot >= 0) {
+	    // More tokens to follow; recursively resolve.
+	    String name = incomplete.substring(pos + 1, dot);
+	    Log child = (Log)children.get(name);
+	    if (child == null)
+		return -1;
+	    else
+		return child.complete(incomplete, dot, candidates);
+	} else {
+	    // Final token, scan children for all partial matches.
+	    String name = incomplete.substring(pos + 1);
+	    for (Iterator i = children.keySet().iterator(); i.hasNext(); ) {
+		String child = (String)i.next();
+		if (child.startsWith(name))
+		    candidates.add(child);
+	    }
+	    switch (candidates.size()) {
+	    case 0:
+		return -1;
+	    case 1:
+		Log child = (Log)children.get(name);
+		if (child != null) {
+		    // The final NAME was an exact match for a child;
+		    // and there are no other possible completions
+		    // (size == 1); change the expansion to either "."
+		    // (have children) or " " (childless).
+		    candidates.remove(0);
+		    synchronized (child) {
+			if (child.children.size() > 0) {
+			    candidates.add(".");
+			} else {
+			    candidates.add(" ");
+			}
+			return incomplete.length();
+		    }
+		} else {
+		    // A single partial completion e.g., <<foo<TAB>>>
+		    // -> <<foobar>>.
+		    return pos + 1;
+		}
+	    default:
+		return pos + 1;
+	    }
+	}
+    }
+
+    /**
+     * Complete the logger path using constructed loggers.  Return the
+     * offset into incomplete where the completions apply, or -1 when
+     * no completions.
+     */
+    public static int complete(String incomplete, List candidates) {
+	return root.complete(incomplete, -1, candidates);
+    }
+
     // Static?
     private static PrintStream out = System.out;
     static void set(PrintStream out) {
diff --git a/frysk-sys/frysk/rsl/TestLog.java b/frysk-sys/frysk/rsl/TestLog.java
index 88f4eef..2833d8d 100644
--- a/frysk-sys/frysk/rsl/TestLog.java
+++ b/frysk-sys/frysk/rsl/TestLog.java
@@ -40,6 +40,7 @@
 package frysk.rsl;
 
 import frysk.junit.TestCase;
+import java.util.LinkedList;
 
 /**
  * Testlogging that is a sub-class of this directory.
@@ -69,6 +70,15 @@ public class TestLog extends TestCase {
 	assertNotNull("self", self);
     }
 
+    public void testPath() {
+	String path = "a.long.path";
+	assertEquals("path", path, get(path).path());
+    }
+
+    public void testName() {
+	assertEquals("name", "path", get("a.long.path").name());
+    }
+
     public void testPeers() {
 	Log lhs = get("the.lhs");
 	Log rhs = get("the.rhs");
@@ -98,5 +108,49 @@ public class TestLog extends TestCase {
 	checkLevel("the.lower.left.hand.side", Level.FINE);
 	checkLevel("the.lower.right", Level.NONE);
     }
-
+    
+    private void checkComplete(String incomplete, int expectedCursor,
+			       String[] expectedCandidates) {
+	// create a tree.
+	get("the.lower.left.hand.side");
+	get("the.lower.left.half");
+	get("the.lower.right.hand.side");
+	// Perfomr a completion
+	LinkedList candidates = new LinkedList();
+	int cursor = root.complete(incomplete, -1, candidates);
+	assertEquals("candidate.size", expectedCandidates.length,
+		     candidates.size());
+	for (int i = 0; i < expectedCandidates.length; i++) {
+	    assertEquals("candidate[" + i + "]", expectedCandidates[i],
+			 candidates.get(i));
+	}
+	assertEquals("cursor", expectedCursor, cursor);
+    }
+    public void testCompleteChildPresent() {
+	// children present, expand the dot
+	checkComplete("the", 3, new String[] {"." });
+    }
+    public void testCompleteChildMissing() {
+	// no children present, expand the space
+	checkComplete("the.lower.left.half", 19, new String[] {" "});
+    }
+    public void testCompleteSingle() {
+	// single completion
+	checkComplete("the.", 4, new String[] {"lower" });
+    }
+    public void testCompleteMultiple() {
+	// multiple completion
+	checkComplete("the.lower.",10,  new String[] { "left", "right" });
+    }
+    public void testCompleteMidway() {
+	// mid completion
+	checkComplete("the.lower.left.h", 15, new String[] { "half", "hand" });
+    }
+    public void testCompleteNothing() {
+	checkComplete("", 0, new String[] { "the" });
+    }
+    public void testCompleteBogus() {
+	// bogus completion
+	checkComplete("the.upper", -1, new String[0]);
+    }
 }


hooks/post-receive
--
frysk system monitor/debugger



More information about the Frysk-cvs mailing list