aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael 'Mickey' Lauer <mickey@vanille-media.de>2005-06-10 20:59:09 +0000
committerMichael 'Mickey' Lauer <mickey@vanille-media.de>2005-06-10 20:59:09 +0000
commit8cf677f9b2c7bd0928b99d10b3507e10d58830d6 (patch)
tree0d7eedf6a2c50ca12c6a4d8d617ad9569f12559c
parent3e08cf83ccf73d84f0783a448d8907e8d9cba388 (diff)
downloadbitbake-8cf677f9b2c7bd0928b99d10b3507e10d58830d6.tar.gz
OO overhaul:
- Introduce classes for commands and the command processor - Autoregister available commands - Fix 'shell' command to work with unlimited number of parameters - Remove 'exec' command
-rw-r--r--lib/bb/shell.py766
1 files changed, 392 insertions, 374 deletions
diff --git a/lib/bb/shell.py b/lib/bb/shell.py
index 9698bddfa..fb12d7a5f 100644
--- a/lib/bb/shell.py
+++ b/lib/bb/shell.py
@@ -28,9 +28,10 @@ TODO:
* command to reparse just one (or more) bbfile(s)
* automatic check if reparsing is necessary (inotify?)
* frontend for bb file manipulation?
- * pipe output of commands into a shell command (i.e grep or sort)?
+ * pipe output of commands into shell commands (i.e grep or sort)?
* job control, i.e. bring commands into background with '&', fg, bg, etc.?
* start parsing in background right after startup?
+ * print variable from package data
* command aliases / shortcuts?
"""
@@ -46,7 +47,7 @@ import sys, os, imp, readline, socket, httplib, urllib, commands
imp.load_source( "bitbake", os.path.dirname( sys.argv[0] )+"/bitbake" )
from bb import data, parse, build, make, fatal
-__version__ = "0.4.2"
+__version__ = "0.5.0"
__credits__ = """BitBake Shell Version %s (C) 2005 Michael 'Mickey' Lauer <mickey@Vanille.de>
Type 'help' for more information, press CTRL-D to exit.""" % __version__
@@ -59,152 +60,188 @@ debug = os.environ.get( "BBSHELL_DEBUG", "" ) != ""
history_file = "%s/.bbsh_history" % os.environ.get( "HOME" )
##########################################################################
-# Commands
+# Class BitBakeShellCommands
##########################################################################
-def bufferCommand( params ):
- """Dump output buffer #i"""
- index = params[0]
- print processCommand.memoryOutput.buffer( int( index ) )
-
-def buffersCommand( params ):
- """Show the available output buffers"""
- commands = processCommand.memoryOutput.bufferedCommands()
- if not commands:
- print "SHELL: No buffered commands available yet. Start doing something."
- else:
- print "="*35, "Available Output Buffers", "="*27
- for index, cmd in enumerate( commands ):
- print "| %s %s" % ( str( index ).ljust( 3 ), cmd )
- print "="*88
-
-def buildCommand( params, cmd = "build" ):
- """Build a providee"""
- name = params[0]
-
- oldcmd = make.options.cmd
- make.options.cmd = cmd
- cooker.build_cache = []
- cooker.build_cache_fail = []
-
- if not parsed:
- print "SHELL: D'oh! The .bb files haven't been parsed yet. Next time call 'parse' before building stuff. This time I'll do it for 'ya."
- parseCommand( None )
- try:
- cooker.buildProvider( name )
- except build.EventException, e:
- print "ERROR: Couldn't build '%s'" % name
- global last_exception
- last_exception = e
-
- make.options.cmd = oldcmd
-
-def cleanCommand( params ):
- """Clean a providee"""
- buildCommand( params, "clean" )
-
-def editCommand( params ):
- """Call $EDITOR on a .bb file"""
- name = params[0]
- os.system( "%s %s" % ( os.environ.get( "EDITOR" ), completeFilePath( name ) ) )
-
-def environmentCommand( params ):
- """Dump out the outer BitBake environment (see bbread)"""
- data.emit_env(sys.__stdout__, make.cfg, True)
-
-def execCommand( params ):
- """Execute one line of python code"""
- exec " ".join( params ) in locals(), globals()
-
-def exitShell( params ):
- """Leave the BitBake Shell"""
- if debug: print "(setting leave_mainloop to true)"
- global leave_mainloop
- leave_mainloop = True
-
-def fileBuildCommand( params, cmd = "build" ):
- """Parse and build a .bb file"""
- name = params[0]
- bf = completeFilePath( name )
- print "SHELL: Calling '%s' on '%s'" % ( cmd, bf )
-
- oldcmd = make.options.cmd
- make.options.cmd = cmd
- cooker.build_cache = []
- cooker.build_cache_fail = []
-
- try:
- bbfile_data = parse.handle( bf, make.cfg )
- except parse.ParseError:
- print "ERROR: Unable to open or parse '%s'" % bf
- else:
- item = data.getVar('PN', bbfile_data, 1)
- data.setVar( "_task_cache", [], bbfile_data ) # force
+class BitBakeShellCommands:
+ """This class contains the valid commands for the shell"""
+
+ def __init__( self, shell ):
+ """Register all the commands"""
+ self._shell = shell
+ for attr in BitBakeShellCommands.__dict__:
+ if not attr.startswith( "__" ):
+ if attr.endswith( "_" ):
+ command = attr[:-1].lower()
+ else:
+ command = attr[:].lower()
+ method = getattr( BitBakeShellCommands, attr )
+ if debug: print "registering command '%s'" % command
+ # scan number of arguments
+ usage = getattr( method, "usage", "" )
+ if usage != "<...>":
+ numArgs = len( usage.split() )
+ else:
+ numArgs = -1
+ shell.registerCommand( command, method, numArgs, "%s %s" % ( command, usage ), method.__doc__ )
+
+ def buffer( self, params ):
+ """Dump specified output buffer"""
+ index = params[0]
+ print self._shell.myout.buffer( int( index ) )
+ buffer.usage = "<index>"
+
+ def buffers( self, params ):
+ """Show the available output buffers"""
+ commands = self._shell.myout.bufferedCommands()
+ if not commands:
+ print "SHELL: No buffered commands available yet. Start doing something."
+ else:
+ print "="*35, "Available Output Buffers", "="*27
+ for index, cmd in enumerate( commands ):
+ print "| %s %s" % ( str( index ).ljust( 3 ), cmd )
+ print "="*88
+
+ def build( self, params, cmd = "build" ):
+ """Build a providee"""
+ name = params[0]
+
+ oldcmd = make.options.cmd
+ make.options.cmd = cmd
+ cooker.build_cache = []
+ cooker.build_cache_fail = []
+
+ if not parsed:
+ print "SHELL: D'oh! The .bb files haven't been parsed yet. Next time call 'parse' before building stuff. This time I'll do it for 'ya."
+ self.parse( None )
try:
- cooker.tryBuildPackage( os.path.abspath( bf ), item, bbfile_data )
+ cooker.buildProvider( name )
except build.EventException, e:
print "ERROR: Couldn't build '%s'" % name
global last_exception
last_exception = e
- make.options.cmd = oldcmd
-
-def fileCleanCommand( params ):
- """Clean a .bb file"""
- fileBuildCommand( params, "clean" )
-
-def fileRebuildCommand( params ):
- """Rebuild (clean & build) a .bb file"""
- fileCleanCommand( params )
- fileBuildCommand( params )
+ make.options.cmd = oldcmd
+ build.usage = "<providee>"
+
+ def clean( self, params ):
+ """Clean a providee"""
+ self.build( params, "clean" )
+ clean.usage = "<providee>"
+
+ def edit( self, params ):
+ """Call $EDITOR on a .bb file"""
+ name = params[0]
+ os.system( "%s %s" % ( os.environ.get( "EDITOR", "vi" ), completeFilePath( name ) ) )
+ edit.usage = "<bbfile>"
+
+ def environment( self, params ):
+ """Dump out the outer BitBake environment (see bbread)"""
+ data.emit_env(sys.__stdout__, make.cfg, True)
+
+ def exit_( self, params ):
+ """Leave the BitBake Shell"""
+ if debug: print "(setting leave_mainloop to true)"
+ global leave_mainloop
+ leave_mainloop = True
+
+ def fileBuild( self, params, cmd = "build" ):
+ """Parse and build a .bb file"""
+ name = params[0]
+ bf = completeFilePath( name )
+ print "SHELL: Calling '%s' on '%s'" % ( cmd, bf )
+
+ oldcmd = make.options.cmd
+ make.options.cmd = cmd
+ cooker.build_cache = []
+ cooker.build_cache_fail = []
-def lastErrorCommand( params ):
- """Show the reason or log that was produced by the last BitBake event exception"""
- if last_exception is None:
- print "SHELL: No Errors yet (Phew)..."
- else:
- reason, event = last_exception.args
- print "SHELL: Reason for the last error: '%s'" % reason
- if ':' in reason:
- msg, filename = reason.split( ':' )
- filename = filename.strip()
- print "SHELL: Dumping log file for last error:"
+ try:
+ bbfile_data = parse.handle( bf, make.cfg )
+ except parse.ParseError:
+ print "ERROR: Unable to open or parse '%s'" % bf
+ else:
+ item = data.getVar('PN', bbfile_data, 1)
+ data.setVar( "_task_cache", [], bbfile_data ) # force
try:
- print open( filename ).read()
- except IOError:
- print "ERROR: Couldn't open '%s'" % filename
-
-def newCommand( params ):
- """Create a new .bb file and open the editor"""
- dirname, filename = params
- packages = '/'.join( data.getVar( "BBFILES", make.cfg, 1 ).split('/')[:-2] )
- fulldirname = "%s/%s" % ( packages, dirname )
-
- if not os.path.exists( fulldirname ):
- print "SHELL: Creating '%s'" % fulldirname
- os.mkdir( fulldirname )
- if os.path.exists( fulldirname ) and os.path.isdir( fulldirname ):
- if os.path.exists( "%s/%s" % ( fulldirname, filename ) ):
- print "SHELL: ERROR: %s/%s already exists" % ( fulldirname, filename )
- return False
- print "SHELL: Creating '%s/%s'" % ( fulldirname, filename )
- newpackage = open( "%s/%s" % ( fulldirname, filename ), "w" )
- print >>newpackage,"""DESCRIPTION = ""
+ cooker.tryBuildPackage( os.path.abspath( bf ), item, bbfile_data )
+ except build.EventException, e:
+ print "ERROR: Couldn't build '%s'" % name
+ global last_exception
+ last_exception = e
+
+ make.options.cmd = oldcmd
+ fileBuild.usage = "<bbfile>"
+
+ def fileClean( self, params ):
+ """Clean a .bb file"""
+ self.fileBuild( params, "clean" )
+ fileClean.usage = "<bbfile>"
+
+ def fileRebuild( self, params ):
+ """Rebuild (clean & build) a .bb file"""
+ self.fileClean( params )
+ self.fileBuild( params )
+ fileRebuild.usage = "<bbfile>"
+
+ def help( self, params ):
+ """Show a comprehensive list of commands and their purpose"""
+ print "="*30, "Available Commands", "="*30
+ allcmds = cmds.keys()
+ allcmds.sort()
+ for cmd in allcmds:
+ function,numparams,usage,helptext = cmds[cmd]
+ print "| %s | %s" % (usage.ljust(30), helptext)
+ print "="*78
+
+ def lastError( self, params ):
+ """Show the reason or log that was produced by the last BitBake event exception"""
+ if last_exception is None:
+ print "SHELL: No Errors yet (Phew)..."
+ else:
+ reason, event = last_exception.args
+ print "SHELL: Reason for the last error: '%s'" % reason
+ if ':' in reason:
+ msg, filename = reason.split( ':' )
+ filename = filename.strip()
+ print "SHELL: Dumping log file for last error:"
+ try:
+ print open( filename ).read()
+ except IOError:
+ print "ERROR: Couldn't open '%s'" % filename
+
+ def new( self, params ):
+ """Create a new .bb file and open the editor"""
+ dirname, filename = params
+ packages = '/'.join( data.getVar( "BBFILES", make.cfg, 1 ).split('/')[:-2] )
+ fulldirname = "%s/%s" % ( packages, dirname )
+
+ if not os.path.exists( fulldirname ):
+ print "SHELL: Creating '%s'" % fulldirname
+ os.mkdir( fulldirname )
+ if os.path.exists( fulldirname ) and os.path.isdir( fulldirname ):
+ if os.path.exists( "%s/%s" % ( fulldirname, filename ) ):
+ print "SHELL: ERROR: %s/%s already exists" % ( fulldirname, filename )
+ return False
+ print "SHELL: Creating '%s/%s'" % ( fulldirname, filename )
+ newpackage = open( "%s/%s" % ( fulldirname, filename ), "w" )
+ print >>newpackage,"""DESCRIPTION = ""
SECTION = ""
AUTHOR = ""
HOMEPAGE = ""
MAINTAINER = ""
LICENSE = "GPL"
+PR = "r0"
SRC_URI = ""
-inherit base
+#inherit base
-#do_compile() {
+#do_configure() {
#
#}
-#do_configure() {
+#do_compile() {
#
#}
@@ -216,126 +253,136 @@ inherit base
#
#}
"""
- newpackage.close()
- os.system( "%s %s/%s" % ( os.environ.get( "EDITOR" ), fulldirname, filename ) )
-
-def pasteBinCommand( params ):
- """Send a command + output buffer to http://pastebin.com"""
- index = params[0]
- contents = processCommand.memoryOutput.buffer( int( index ) )
- status, error, location = sendToPastebin( contents )
- if status == 302:
- print "SHELL: Pasted to %s" % location
- else:
- print "ERROR: %s %s" % ( response.status, response.reason )
+ newpackage.close()
+ os.system( "%s %s/%s" % ( os.environ.get( "EDITOR" ), fulldirname, filename ) )
+ new.usage = "<directory> <filename>"
+
+ def pasteBin( self, params ):
+ """Send a command + output buffer to http://pastebin.com"""
+ index = params[0]
+ contents = self._shell.myout.buffer( int( index ) )
+ status, error, location = sendToPastebin( contents )
+ if status == 302:
+ print "SHELL: Pasted to %s" % location
+ else:
+ print "ERROR: %s %s" % ( response.status, response.reason )
+ pasteBin.usage = "<index>"
-def pasteLogCommand( params ):
- """Send the last event exception error log (if there is one) to http://pastebin.com"""
- if last_exception is None:
- print "SHELL: No Errors yet (Phew)..."
- else:
- reason, event = last_exception.args
- print "SHELL: Reason for the last error: '%s'" % reason
- if ':' in reason:
- msg, filename = reason.split( ':' )
- filename = filename.strip()
- print "SHELL: Pasting log file to pastebin..."
-
- status, error, location = sendToPastebin( open( filename ).read() )
-
- if status == 302:
- print "SHELL: Pasted to %s" % location
- else:
- print "ERROR: %s %s" % ( response.status, response.reason )
-
-def parseCommand( params ):
- """(Re-)parse .bb files and calculate the dependency graph"""
- cooker.status = cooker.ParsingStatus()
- ignore = data.getVar("ASSUME_PROVIDED", make.cfg, 1) or ""
- cooker.status.ignored_dependencies = set( ignore.split() )
- cooker.handleCollections( data.getVar("BBFILE_COLLECTIONS", make.cfg, 1) )
-
- make.collect_bbfiles( cooker.myProgressCallback )
- cooker.buildDepgraph()
- global parsed
- parsed = True
- print
-
-def printCommand( params ):
- """Print the contents of an outer BitBake environment variable"""
- var = params[0]
- value = data.getVar( var, make.cfg, 1 )
- print value
-
-def pythonCommand( params ):
- """Enter the expert mode - an interactive BitBake Python Interpreter"""
- sys.ps1 = "EXPERT BB>>> "
- sys.ps2 = "EXPERT BB... "
- import code
- python = code.InteractiveConsole( dict( globals() ) )
- python.interact( "SHELL: Expert Mode - BitBake Python %s\nType 'help' for more information, press CTRL-D to switch back to BBSHELL." % sys.version )
-
-def setVarCommand( params ):
- """Set an outer BitBake environment variable"""
- var, value = params
- data.setVar( var, value, make.cfg )
- print "OK"
-
-def rebuildCommand( params ):
- """Clean and rebuild a .bb file or a providee"""
- buildCommand( params, "clean" )
- buildCommand( params, "build" )
-
-def shellCommand( params ):
- """Execute a shell command and dump the output"""
- print commands.getoutput( " ".join( params ) )
-
-def statusCommand( params ):
- print "-" * 78
- print "build cache = '%s'" % cooker.build_cache
- print "build cache fail = '%s'" % cooker.build_cache_fail
- print "building list = '%s'" % cooker.building_list
- print "build path = '%s'" % cooker.build_path
- print "consider_msgs_cache = '%s'" % cooker.consider_msgs_cache
- print "build stats = '%s'" % cooker.stats
- if last_exception is not None: print "last_exception = '%s'" % repr( last_exception.args )
- print "memory output contents = '%s'" % processCommand.memoryOutput._buffer
-
-def testCommand( params ):
- """Just for testing..."""
- print "testCommand called with '%s'" % params
-
-def whichCommand( params ):
- """Computes the providers for a given providee"""
- item = params[0]
-
- if not parsed:
- print "SHELL: D'oh! The .bb files haven't been parsed yet. Next time call 'parse' before building stuff. This time I'll do it for 'ya."
- parseCommand( None )
-
- preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, make.cfg, 1 )
- if not preferred: preferred = item
-
- try:
- lv, lf, pv, pf = cooker.findBestProvider( preferred )
- except KeyError:
- lv, lf, pv, pf = (None,)*4
-
- try:
- providers = cooker.status.providers[item]
- except KeyError:
- print "SHELL: ERROR: Nothing provides", preferred
- else:
- for provider in providers:
- if provider == pf: provider = " (***) %s" % provider
- else: provider = " %s" % provider
- print provider
+ def pasteLog( self, params ):
+ """Send the last event exception error log (if there is one) to http://pastebin.com"""
+ if last_exception is None:
+ print "SHELL: No Errors yet (Phew)..."
+ else:
+ reason, event = last_exception.args
+ print "SHELL: Reason for the last error: '%s'" % reason
+ if ':' in reason:
+ msg, filename = reason.split( ':' )
+ filename = filename.strip()
+ print "SHELL: Pasting log file to pastebin..."
+
+ status, error, location = sendToPastebin( open( filename ).read() )
+
+ if status == 302:
+ print "SHELL: Pasted to %s" % location
+ else:
+ print "ERROR: %s %s" % ( response.status, response.reason )
+
+ def parse( self, params ):
+ """(Re-)parse .bb files and calculate the dependency graph"""
+ cooker.status = cooker.ParsingStatus()
+ ignore = data.getVar("ASSUME_PROVIDED", make.cfg, 1) or ""
+ cooker.status.ignored_dependencies = set( ignore.split() )
+ cooker.handleCollections( data.getVar("BBFILE_COLLECTIONS", make.cfg, 1) )
+
+ make.collect_bbfiles( cooker.myProgressCallback )
+ cooker.buildDepgraph()
+ global parsed
+ parsed = True
+ print
+
+ def print_( self, params ):
+ """Print the contents of an outer BitBake environment variable"""
+ var = params[0]
+ value = data.getVar( var, make.cfg, 1 )
+ print value
+ print_.usage = "<variable>"
+
+ def python( self, params ):
+ """Enter the expert mode - an interactive BitBake Python Interpreter"""
+ sys.ps1 = "EXPERT BB>>> "
+ sys.ps2 = "EXPERT BB... "
+ import code
+ interpreter = code.InteractiveConsole( dict( globals() ) )
+ interpreter.interact( "SHELL: Expert Mode - BitBake Python %s\nType 'help' for more information, press CTRL-D to switch back to BBSHELL." % sys.version )
+
+ def setVar( self, params ):
+ """Set an outer BitBake environment variable"""
+ var, value = params
+ data.setVar( var, value, make.cfg )
+ print "OK"
+ setVar.usage = "<variable> <value>"
+
+ def rebuild( self, params ):
+ """Clean and rebuild a .bb file or a providee"""
+ self.build( params, "clean" )
+ self.build( params, "build" )
+ rebuild.usage = "<providee>"
+
+ def shell( self, params ):
+ """Execute a shell command and dump the output"""
+ if params != "":
+ print commands.getoutput( " ".join( params ) )
+ shell.usage = "<...>"
+
+ def status( self, params ):
+ """<just for testing>"""
+ print "-" * 78
+ print "build cache = '%s'" % cooker.build_cache
+ print "build cache fail = '%s'" % cooker.build_cache_fail
+ print "building list = '%s'" % cooker.building_list
+ print "build path = '%s'" % cooker.build_path
+ print "consider_msgs_cache = '%s'" % cooker.consider_msgs_cache
+ print "build stats = '%s'" % cooker.stats
+ if last_exception is not None: print "last_exception = '%s'" % repr( last_exception.args )
+ print "memory output contents = '%s'" % self._shell.myout._buffer
+
+ def test( self, params ):
+ """<just for testing>"""
+ print "testCommand called with '%s'" % params
+
+ def which( self, params ):
+ """Computes the providers for a given providee"""
+ item = params[0]
+
+ if not parsed:
+ print "SHELL: D'oh! The .bb files haven't been parsed yet. Next time call 'parse' before building stuff. This time I'll do it for 'ya."
+ self.parse( None )
+
+ preferred = data.getVar( "PREFERRED_PROVIDER_%s" % item, make.cfg, 1 )
+ if not preferred: preferred = item
+
+ try:
+ lv, lf, pv, pf = cooker.findBestProvider( preferred )
+ except KeyError:
+ lv, lf, pv, pf = (None,)*4
+
+ try:
+ providers = cooker.status.providers[item]
+ except KeyError:
+ print "SHELL: ERROR: Nothing provides", preferred
+ else:
+ for provider in providers:
+ if provider == pf: provider = " (***) %s" % provider
+ else: provider = " %s" % provider
+ print provider
+ which.usage = "<providee>"
##########################################################################
# Common helper functions
##########################################################################
def completeFilePath( bbfile ):
+ """Get the complete bbfile path"""
if not make.pkgdata: return bbfile
for key in make.pkgdata.keys():
if key.endswith( bbfile ):
@@ -343,6 +390,7 @@ def completeFilePath( bbfile ):
return bbfile
def sendToPastebin( content ):
+ """Send content to http://www.pastebin.com"""
mydata = {}
mydata["parent_pid"] = ""
mydata["format"] = "bash"
@@ -360,11 +408,42 @@ def sendToPastebin( content ):
return response.status, response.reason, response.getheader( "location" ) or "unknown"
+def completer( text, state ):
+ """Return a possible readline completion"""
+ if debug: print "(completer called with text='%s', state='%d'" % ( text, state )
+
+ if state == 0:
+ line = readline.get_line_buffer()
+ if " " in line:
+ line = line.split()
+ # we are in second (or more) argument
+ if line[0] == "print" or line[0] == "set":
+ allmatches = make.cfg.keys()
+ elif line[0].startswith( "file" ):
+ if make.pkgdata is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
+ else: allmatches = [ x.split("/")[-1] for x in make.pkgdata.keys() ]
+ elif line[0] == "build" or line[0] == "clean" or line[0] == "which":
+ if make.pkgdata is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
+ else: allmatches = cooker.status.providers.iterkeys()
+ else: allmatches = [ "(No tab completion available for this command)" ]
+ else:
+ # we are in first argument
+ allmatches = cmds.iterkeys()
+
+ completer.matches = [ x for x in allmatches if x[:len(text)] == text ]
+ #print "completer.matches = '%s'" % completer.matches
+ if len( completer.matches ) > state:
+ return completer.matches[state]
+ else:
+ return None
+
+
##########################################################################
-# File-like output class buffering the output of the last 10 commands
+# Class MemoryOutput
##########################################################################
class MemoryOutput:
+ """File-like output class buffering the output of the last 10 commands"""
def __init__( self, delegate ):
self.delegate = delegate
self._buffer = []
@@ -400,152 +479,91 @@ class MemoryOutput:
return self.delegate.isatty()
##########################################################################
-# Startup / Shutdown
+# Class BitBakeShell
##########################################################################
-def init():
- """Register commands and set up readline"""
- registerCommand( "help", showHelp )
- registerCommand( "exit", exitShell )
-
- registerCommand( "buffer", bufferCommand, 1, "buffer <#>" )
- registerCommand( "buffers", buffersCommand, 0 )
- registerCommand( "build", buildCommand, 1, "build <providee>" )
- registerCommand( "clean", cleanCommand, 1, "clean <providee>" )
- registerCommand( "edit", editCommand, 1, "edit <bbfile>" )
- registerCommand( "environment", environmentCommand )
- registerCommand( "exec", execCommand, 1, "exec <one line of pythoncode>" )
- registerCommand( "filebuild", fileBuildCommand, 1, "filebuild <bbfile>" )
- registerCommand( "fileclean", fileCleanCommand, 1, "fileclean <bbfile>" )
- registerCommand( "filerebuild", fileRebuildCommand, 1, "filerebuild <bbfile>" )
- registerCommand( "lastlog", lastErrorCommand, 0 )
- registerCommand( "new", newCommand, 2, "new <directory> <bbfile>" )
- registerCommand( "pastebin", pasteBinCommand, 1, "pastebin <#>" )
- registerCommand( "pastelog", pasteLogCommand, 0 )
- registerCommand( "parse", parseCommand )
- registerCommand( "print", printCommand, 1, "print <variable>" )
- registerCommand( "python", pythonCommand )
- registerCommand( "rebuild", rebuildCommand, 1, "rebuild <providee>" )
- registerCommand( "set", setVarCommand, 2, "set <variable> <value>" )
- registerCommand( "shell", shellCommand, 1, "shell <command>" )
- registerCommand( "status", statusCommand )
- registerCommand( "test", testCommand )
- registerCommand( "which", whichCommand, 1, "which <providee>" )
-
- readline.set_completer( completer )
- readline.set_completer_delims( " " )
- readline.parse_and_bind("tab: complete")
-
- try:
- global history_file
- readline.read_history_file( history_file )
- except IOError:
- pass # It doesn't exist yet.
-
-def cleanup():
- """Write readline history and clean up resources"""
- if debug: print "(writing command history)"
- try:
- global history_file
- readline.write_history_file( history_file )
- except:
- print "SHELL: Unable to save command history"
+class BitBakeShell:
-def completer( text, state ):
- """Return a possible readline completion"""
- if debug: print "(completer called with text='%s', state='%d'" % ( text, state )
+ def __init__( self ):
+ """Register commands and set up readline"""
+ self.commands = BitBakeShellCommands( self )
+ self.myout = MemoryOutput( sys.stdout )
- if state == 0:
- line = readline.get_line_buffer()
- if " " in line:
- line = line.split()
- # we are in second (or more) argument
- if line[0] == "print" or line[0] == "set":
- allmatches = make.cfg.keys()
- elif line[0].startswith( "file" ):
- if make.pkgdata is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
- else: allmatches = [ x.split("/")[-1] for x in make.pkgdata.keys() ]
- elif line[0] == "build" or line[0] == "clean" or line[0] == "which":
- if make.pkgdata is None: allmatches = [ "(No Matches Available. Parsed yet?)" ]
- else: allmatches = cooker.status.providers.iterkeys()
- else: allmatches = [ "(No tab completion available for this command)" ]
- else:
- # we are in first argument
- allmatches = cmds.iterkeys()
-
- completer.matches = [ x for x in allmatches if x[:len(text)] == text ]
- #print "completer.matches = '%s'" % completer.matches
- if len( completer.matches ) > state:
- return completer.matches[state]
- else:
- return None
+ readline.set_completer( completer )
+ readline.set_completer_delims( " " )
+ readline.parse_and_bind("tab: complete")
-def showCredits():
- """Show credits (sic!)"""
- print __credits__
-
-def showHelp( *args ):
- """Show a comprehensive list of commands and their purpose"""
- print "="*35, "Available Commands", "="*35
- allcmds = cmds.keys()
- allcmds.sort()
- for cmd in allcmds:
- function,numparams,usage,helptext = cmds[cmd]
- print "| %s | %s" % (usage.ljust(35), helptext)
- print "="*88
-
-def registerCommand( command, function, numparams = 0, usage = "", helptext = "" ):
- """Register a command"""
- if usage == "": usage = command
- if helptext == "": helptext = function.__doc__ or "<not yet documented>"
- cmds[command] = ( function, numparams, usage, helptext )
-
-def processCommand( command, params ):
- """Process a command. Check number of params and print a usage string, if appropriate"""
- if debug: print "(processing command '%s'...)" % command
- try:
- function, numparams, usage, helptext = cmds[command]
- except KeyError:
- print "SHELL: ERROR: '%s' command is not a valid command." % command
- processCommand.memoryOutput.removeLast()
- else:
- if not len( params ) == numparams:
- print "Usage: '%s'" % usage
- return
+ try:
+ global history_file
+ readline.read_history_file( history_file )
+ except IOError:
+ pass # It doesn't exist yet.
- result = function( params )
- if debug: print "(result was '%s')" % result
+ print __credits__
-def main():
- """The main command loop"""
- processCommand.memoryOutput = MemoryOutput( sys.stdout )
- while not leave_mainloop:
+ def cleanup( self ):
+ """Write readline history and clean up resources"""
+ if debug: print "(writing command history)"
try:
- sys.stdout = processCommand.memoryOutput.delegate
- cmdline = raw_input( "BB>> " )
- sys.stdout = processCommand.memoryOutput
- if cmdline:
- commands = cmdline.split( ';' )
- for command in commands:
- processCommand.memoryOutput.startCommand( command )
- if ' ' in command:
- processCommand( command.split()[0], command.split()[1:] )
- else:
- processCommand( command, "" )
- processCommand.memoryOutput.endCommand()
- except EOFError:
- print
- return
- except KeyboardInterrupt:
- print
+ global history_file
+ readline.write_history_file( history_file )
+ except:
+ print "SHELL: Unable to save command history"
+
+ def registerCommand( self, command, function, numparams = 0, usage = "", helptext = "" ):
+ """Register a command"""
+ if usage == "": usage = command
+ if helptext == "": helptext = function.__doc__ or "<not yet documented>"
+ cmds[command] = ( function, numparams, usage, helptext )
+
+ def processCommand( self, command, params ):
+ """Process a command. Check number of params and print a usage string, if appropriate"""
+ if debug: print "(processing command '%s'...)" % command
+ try:
+ function, numparams, usage, helptext = cmds[command]
+ except KeyError:
+ print "SHELL: ERROR: '%s' command is not a valid command." % command
+ self.myout.removeLast()
+ else:
+ if (numparams != -1) and (not len( params ) == numparams):
+ print "Usage: '%s'" % usage
+ return
+
+ result = function( self.commands, params )
+ if debug: print "(result was '%s')" % result
+
+ def main( self ):
+ """The main command loop"""
+ while not leave_mainloop:
+ try:
+ sys.stdout = self.myout.delegate
+ cmdline = raw_input( "BB>> " )
+ sys.stdout = self.myout
+ if cmdline:
+ commands = cmdline.split( ';' )
+ for command in commands:
+ self.myout.startCommand( command )
+ if ' ' in command:
+ self.processCommand( command.split()[0], command.split()[1:] )
+ else:
+ self.processCommand( command, "" )
+ self.myout.endCommand()
+ except EOFError:
+ print
+ return
+ except KeyboardInterrupt:
+ print
+
+##########################################################################
+# Start function - called from the BitBake command line utility
+##########################################################################
def start( aCooker ):
global cooker
cooker = aCooker
- showCredits()
- init()
- main()
- cleanup()
+ bbshell = BitBakeShell()
+ bbshell.main()
+ bbshell.cleanup()
if __name__ == "__main__":
print "SHELL: Sorry, this program should only be called by BitBake."