Index: trunk/src/VBox/Frontends/VBoxShell/vboxshell.py
===================================================================
--- trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 28679)
+++ trunk/src/VBox/Frontends/VBoxShell/vboxshell.py	(revision 28716)
@@ -136,11 +136,29 @@
        print "onGuestPropertyChange: %s: %s=%s" %(id, name, newValue)
 
-g_hasreadline = 1
+g_hasreadline = True
 try:
     import readline
     import rlcompleter
 except:
-    g_hasreadline = 0
-
+    g_hasreadline = False
+
+
+g_hascolors = True
+term_colors = {
+    'red':'\033[31m',
+    'blue':'\033[94m',
+    'green':'\033[92m',
+    'yellow':'\033[93m',
+    'magenta':'\033[35m'
+    }
+def colored(str,color):
+    if not g_hascolors:
+        return str
+    global term_colors
+    col = term_colors.get(color,None)
+    if col:
+        return col+str+'\033[0m'
+    else:
+        return str
 
 if g_hasreadline:
@@ -189,6 +207,7 @@
                     matches.append(word)
         except Exception,e:
-            traceback.print_exc()
-            print e
+            printErr(e)
+            if g_verbose:
+                traceback.print_exc()
 
         return matches
@@ -207,9 +226,15 @@
   readline.set_completer_delims(re.sub("[\\.]", "", delims)) # remove some of the delimiters
   # OSX need it
+  readline.parse_and_bind("set editing-mode emacs")
   if platform.system() == 'Darwin':
+      # see http://www.certif.com/spec_help/readline.html
       readline.parse_and_bind ("bind ^I rl_complete")
+      readline.parse_and_bind ("bind ^W ed-delete-prev-word")
+      # Doesn't work well
+      # readline.parse_and_bind ("bind ^R em-inc-search-prev")
   readline.parse_and_bind("tab: complete")
 
-g_verbose = True
+
+g_verbose = False
 
 def split_no_quotes(s):
@@ -219,5 +244,5 @@
     try:
         while not p.completed:
-            print "%d %%\r" %(p.percent),
+            print "%s %%\r" %(colored(str(p.percent),'red')),
             sys.stdout.flush()
             p.waitForCompletion(wait)
@@ -231,8 +256,17 @@
         return 0
 
+def printErr(ctx,e):
+     print colored(str(e), 'red')
+
 def reportError(ctx,progress):
     ei = progress.errorInfo
     if ei:
-        print "Error in %s: %s" %(ei.component, ei.text)
+        print colored("Error in %s: %s" %(ei.component, ei.text), 'red')
+
+def colCat(ctx,str):
+    return colored(str, 'magenta')
+
+def colVm(ctx,vm):
+    return colored(vm, 'blue')
 
 def createVm(ctx,name,kind,base):
@@ -272,5 +306,5 @@
             perf.setup(['*'], [mach], 10, 15)
           except Exception,e:
-            print e
+            printErr(ctx, e)
             if g_verbose:
                 traceback.print_exc()
@@ -306,7 +340,7 @@
 def asState(var):
     if var:
-        return 'on'
-    else:
-        return 'off'
+        return colored('on', 'green')
+    else:
+        return colored('off', 'green')
 
 def asFlag(var):
@@ -457,11 +491,11 @@
 
 def printHostUsbDev(ctx,ud):
-    print "  %s: %s (vendorId=%d productId=%d serial=%s) %s" %(ud.id, ud.product, ud.vendorId, ud.productId, ud.serialNumber,getUSBStateString(ud.state))
+    print "  %s: %s (vendorId=%d productId=%d serial=%s) %s" %(ud.id, colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber,asEnumElem(ctx, 'USBDeviceState', ud.state))
 
 def printUsbDev(ctx,ud):
-    print "  %s: %s (vendorId=%d productId=%d serial=%s)" %(ud.id, ud.product, ud.vendorId, ud.productId, ud.serialNumber)
+    print "  %s: %s (vendorId=%d productId=%d serial=%s)" %(ud.id,  colored(ud.product,'blue'), ud.vendorId, ud.productId, ud.serialNumber)
 
 def printSf(ctx,sf):
-    print "name=%s host=%s %s %s" %(sf.name, sf.hostPath, cond(sf.accessible, "accessible", "not accessible"), cond(sf.writable, "writable", "read-only"))
+    print "    name=%s host=%s %s %s" %(sf.name, sf.hostPath, cond(sf.accessible, "accessible", "not accessible"), cond(sf.writable, "writable", "read-only"))
 
 def ginfo(ctx,console, args):
@@ -497,5 +531,5 @@
         progress = vb.openExistingSession(session, uuid)
     except Exception,e:
-        print "Session to '%s' not open: %s" %(mach.name,e)
+        printErr(ctx, "Session to '%s' not open: %s" %(mach.name,str(e)))
         if g_verbose:
             traceback.print_exc()
@@ -530,5 +564,5 @@
         ops[cmd]()
     except Exception, e:
-        print 'failed: ',e
+        printErr(ctx,e)
         if g_verbose:
             traceback.print_exc()
@@ -543,5 +577,5 @@
          cmd(ctx, mach, args)
     except Exception, e:
-        print 'failed: ',e
+        printErr(ctx,e)
         if g_verbose:
             traceback.print_exc()
@@ -579,5 +613,5 @@
     else:
         spec = ""
-    print "    %s: %s%s" %(cmd,h,spec)
+    print "    %s: %s%s" %(colored(cmd,'blue'),h,spec)
 
 def helpCmd(ctx, args):
@@ -601,6 +635,6 @@
     for e in all.keys():
         if str(elem) == str(all[e]):
-            return e
-    return "<unknown>"
+            return colored(e, 'green')
+    return colored("<unknown>", 'green')
 
 def enumFromString(ctx,enum,str):
@@ -614,5 +648,5 @@
         else:
             tele = "    "
-        print "%sMachine '%s' [%s], state=%s" %(tele,m.name,m.id,asEnumElem(ctx,"SessionState", m.sessionState))
+        print "%sMachine '%s' [%s], state=%s" %(tele,colVm(ctx,m.name),m.id,asEnumElem(ctx,"SessionState", m.sessionState))
     return 0
 
@@ -626,5 +660,5 @@
     os = ctx['vb'].getGuestOSType(mach.OSTypeId)
     print " One can use setvar <mach> <var> <value> to change variable, using name in []."
-    print "  Name [name]: %s" %(mach.name)
+    print "  Name [name]: %s" %(colVm(ctx,mach.name))
     print "  Description [description]: %s" %(mach.description)
     print "  ID [n/a]: %s" %(mach.id)
@@ -671,5 +705,5 @@
     if controllers:
         print
-        print "  Controllers:"
+        print colCat(ctx,"  Controllers:")
     for controller in controllers:
         print "    '%s': bus %s type %s" % (controller.name, asEnumElem(ctx,"StorageBus", controller.bus), asEnumElem(ctx,"StorageControllerType", controller.controllerType))
@@ -678,5 +712,5 @@
     if attaches:
         print
-        print "  Mediums:"
+        print colCat(ctx,"  Mediums:")
     for a in attaches:
         print "   Controller: '%s' port/device: %d:%d type: %s (%s):" % (a.controller, a.port, a.device, asEnumElem(ctx,"DeviceType", a.type), a.type)
@@ -712,4 +746,8 @@
                     print "    Virtual image at %s" %(m.location)
                     print "    Size: %s" %(m.size)
+
+    print colCat(ctx,"   Shared folders:")
+    for sf in ctx['global'].getArray(mach, 'sharedFolders'):
+        printSf(ctx,sf)
 
     return 0
@@ -1059,47 +1097,44 @@
     return 0
 
-def getUSBStateString(state):
-    if state == 0:
-        return "NotSupported"
-    elif state == 1:
-        return "Unavailable"
-    elif state == 2:
-        return "Busy"
-    elif state == 3:
-        return "Available"
-    elif state == 4:
-        return "Held"
-    elif state == 5:
-        return "Captured"
-    else:
-        return "Unknown"
+def colorsCmd(ctx, args):
+    global g_hascolors
+    g_hascolors = not g_hascolors
+    return 0
 
 def hostCmd(ctx, args):
-   host = ctx['vb'].host
+   vb = ctx['vb']
+   print "VirtualBox version %s" %(vb.version)
+   #print "Global shared folders:"
+   #for ud in ctx['global'].getArray(vb, 'sharedFolders'):
+   #    printSf(ctx,sf)
+   host = vb.host
    cnt = host.processorCount
-   print "Processors available/online: %d/%d " %(cnt,host.processorOnlineCount)
+   print colCat(ctx,"Processors:")
+   print "  available/online: %d/%d " %(cnt,host.processorOnlineCount)
    for i in range(0,cnt):
-      print "Processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
-
-   print "RAM: %dM (free %dM)" %(host.memorySize, host.memoryAvailable)
-   print "OS: %s (%s)" %(host.operatingSystem, host.OSVersion)
+       print "  processor #%d speed: %dMHz %s" %(i,host.getProcessorSpeed(i), host.getProcessorDescription(i))
+
+   print colCat(ctx, "RAM:")
+   print "  %dM (free %dM)" %(host.memorySize, host.memoryAvailable)
+   print colCat(ctx,"OS:");
+   print "  %s (%s)" %(host.operatingSystem, host.OSVersion)
    if host.Acceleration3DAvailable:
-       print "3D acceleration available"
+       print colCat(ctx,"3D acceleration available")
    else:
-       print "3D acceleration NOT available"
-
-   print "Network interfaces:"
+       print colCat(ctx,"3D acceleration NOT available")
+
+   print colCat(ctx,"Network interfaces:")
    for ni in ctx['global'].getArray(host, 'networkInterfaces'):
        print "  %s (%s)" %(ni.name, ni.IPAddress)
 
-   print "DVD drives:"
+   print colCat(ctx,"DVD drives:")
    for dd in ctx['global'].getArray(host, 'DVDDrives'):
        print "  %s - %s" %(dd.name, dd.description)
 
-   print "Floppy drives:"
+   print colCat(ctx,"Floppy drives:")
    for dd in ctx['global'].getArray(host, 'floppyDrives'):
        print "  %s - %s" %(dd.name, dd.description)
 
-   print "USB devices:"
+   print colCat(ctx,"USB devices:")
    for ud in ctx['global'].getArray(host, 'USBDevices'):
        printHostUsbDev(ctx,ud)
@@ -1183,17 +1218,17 @@
 def showLogCmd(ctx, args):
     if (len(args) < 2):
-        print "usage: showLog <vm> <num>"
-        return 0
-    mach = argsToMach(ctx,args)
-    if mach == None:
-        return 0
-
-    log = 0;
+        print "usage: showLog vm <num>"
+        return 0
+    mach = argsToMach(ctx,args)
+    if mach == None:
+        return 0
+
+    log = 0
     if (len(args) > 2):
-       log  = args[2];
-
-    uOffset = 0;
+       log  = args[2]
+
+    uOffset = 0
     while True:
-        data = mach.readLog(log, uOffset, 1024*1024)
+        data = mach.readLog(log, uOffset, 4096)
         if (len(data) == 0):
             break
@@ -1204,4 +1239,34 @@
     return 0
 
+def findLogCmd(ctx, args):
+    if (len(args) < 3):
+        print "usage: findLog vm pattern <num>"
+        return 0
+    mach = argsToMach(ctx,args)
+    if mach == None:
+        return 0
+
+    log = 0
+    if (len(args) > 3):
+       log  = args[3]
+
+    pattern = args[2]
+    uOffset = 0
+    while True:
+        # to reduce line splits on buffer boundary
+        data = mach.readLog(log, uOffset, 512*1024)
+        if (len(data) == 0):
+            break
+        d = str(data).split("\n")
+        for s in d:
+            m = re.findall(pattern, s)
+            if len(m) > 0:
+                for mt in m:
+                    s = s.replace(mt, colored(mt,'red'))
+                print s
+        uOffset += len(data)
+
+    return 0
+
 def evalCmd(ctx, args):
    expr = ' '.join(args[1:])
@@ -1209,5 +1274,5 @@
         exec expr
    except Exception, e:
-        print 'failed: ',e
+        printErr(ctx,e)
         if g_verbose:
             traceback.print_exc()
@@ -1236,7 +1301,7 @@
             if done != 0: break
     except Exception,e:
-        print "error:",e
+        printErr(ctx,e)
         if g_verbose:
-                traceback.print_exc()
+            traceback.print_exc()
     lf.close()
     return 0
@@ -1965,4 +2030,47 @@
    return 0
 
+def shareFolderCmd(ctx,args):
+    if (len(args) < 4):
+        print "usage: shareFolder vm path name <writable> <persistent>"
+        return 0
+
+    mach = argsToMach(ctx,args)
+    if mach is None:
+        return 0
+    path = args[2]
+    name = args[3]
+    writable = False
+    persistent = False
+    if len(args) > 4:
+        for a in args[4:]:
+            if a == 'writable':
+                writable = True
+            if a == 'persistent':
+                persistent = True
+    if persistent:
+        cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.createSharedFolder(name, path, writable), [])
+    else:
+        cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.createSharedFolder(name, path, writable)])
+    return 0
+
+def unshareFolderCmd(ctx,args):
+    if (len(args) < 3):
+        print "usage: unshareFolder vm name"
+        return 0
+
+    mach = argsToMach(ctx,args)
+    if mach is None:
+        return 0
+    name = args[2]
+    found = False
+    for sf in ctx['global'].getArray(mach, 'sharedFolders'):
+        if sf.name == name:
+            cmdClosedVm(ctx, mach, lambda ctx,mach,args: mach.removeSharedFolder(name), [])
+            found = True
+            break
+    if not found:
+        cmdExistingVm(ctx, mach, 'guestlambda', [lambda ctx,mach,console,args: console.removeSharedFolder(name)])
+    return 0
+
 aliases = {'s':'start',
            'i':'info',
@@ -1999,4 +2107,5 @@
             'portForward':['Setup permanent port forwarding for a VM, takes adapter number host port and guest port: portForward Win32 0 8080 80', portForwardCmd, 0],
             'showLog':['Show log file of the VM, : showLog Win32', showLogCmd, 0],
+            'findLog':['Show entries matching pattern in log file of the VM, : findLog Win32 PDM|CPUM', findLogCmd, 0],
             'reloadExt':['Reload custom extensions: reloadExt', reloadExtCmd, 0],
             'runScript':['Run VBox script: runScript script.vbox', runScriptCmd, 0],
@@ -2030,8 +2139,11 @@
             'detachCtr': ['Detach HDD from the VM: detachCtr win Ctr0', detachCtrCmd, 0],
             'attachUsb': ['Attach USB device to the VM (use listUsb to show available devices): attachUsb win uuid', attachUsbCmd, 0],
-            'detachUsb': ['Detach USB device from the VM: detachUsb win uui', detachUsbCmd, 0],
+            'detachUsb': ['Detach USB device from the VM: detachUsb win uuid', detachUsbCmd, 0],
             'listMediums': ['List mediums known to this VBox instance', listMediumsCmd, 0],
             'listUsb': ['List known USB devices', listUsbCmd, 0],
-            'gui': ['Start GUI frontend', guiCmd, 0]
+            'shareFolder': ['Make host\'s folder visible to guest: shareFolder win /share share writable', shareFolderCmd, 0],
+            'unshareFolder': ['Remove folder sharing', unshareFolderCmd, 0],
+            'gui': ['Start GUI frontend', guiCmd, 0],
+            'colors':['Toggle colors', colorsCmd, 0],
             }
 
@@ -2135,14 +2247,13 @@
     while True:
         try:
-            cmd = raw_input("vbox> ")
+            cmd = raw_input(colored("vbox> ", 'blue'))
             done = runCommand(ctx, cmd)
             if done != 0: break
         except KeyboardInterrupt:
             print '====== You can type quit or q to leave'
+        except EOFError:
             break
-        except EOFError:
-            break;
         except Exception,e:
-            print e
+            printErr(ctx,e)
             if g_verbose:
                 traceback.print_exc()
