fix bash-completion

This commit is contained in:
2023-10-17 00:47:21 +08:00
parent 6cb42d6b8d
commit b89a492b6a
6 changed files with 420 additions and 14 deletions

View File

@@ -1,4 +1,7 @@
# sunhpc(1) completion
#
# /etc/bash_completion.d/sunhpc
#
_sunhpc_array_delete_at()
{
@@ -40,8 +43,11 @@ _sunhpc()
return 0
fi
local IFS=$'\n'
COMPREPLY=( $( compgen -W '$output' -- $cur ) )
#local IFS=$'\n'
COMPREPLY=( $( compgen -W '$output' -- ${cur} ) )
# do not append a space to words that end with =
[[ $COMPREPLY == *= ]] && compopt -o nospace
} &&
complete -F _sunhpc sunhpc

View File

@@ -67,7 +67,6 @@ class Command(sunhpc.commands.report.command):
if o.MustBeRoot and not self.isRootUser():
sys.exit(0)
results = []
for arg in o.usage().split():
tmp = arg.split('=', 1)
@@ -77,14 +76,9 @@ class Command(sunhpc.commands.report.command):
tmpstr = arg.replace('[', '')
tmpstr = tmpstr.replace(']', '')
tmpstr = tmpstr.split('=')[0] + '='
results.append(tmpstr)
#print (' '.join(results))
#print ('--add-interface= --set-net=')
print ('--envs= prefix=')
print (' '.join(results))
RollName = "base"

358
lib/sunhpc/core/app.py Normal file
View File

@@ -0,0 +1,358 @@
#
# Time for an initial checkin. Datastructure and general layout of the
# code is correct. Still need comparison code for File and RPM objects.
#
import os
import sys
import types
import sunhpc
import getopt
import sunhpc.invoke
import xml
from xml.sax import saxutils
from xml.sax import handler
from xml.sax import make_parser
from xml.sax._exceptions import SAXParseException
class Application:
def __init__(self, argv=None):
# Applets (code in the kickstart graph) doesn't pass sys.argv
# so pick it up anyway to keep everything working.
if not argv:
argv = sys.argv
self.args = []
self.caller_args = argv[1:]
self.usage_command = os.path.basename(argv[0])
self.usage_name = 'Application'
self.usage_version = 0
self.rcfileHandler = RCFileHandler
self.rcfileList = []
self.rcForce = []
self.projectName = 'sunhpc'
self.projectVersionName = 'base'
self.projectVersionMajor = sunhpc.version_major
self.projectVersionMinor = sunhpc.version_minor
self.projectVersionMicro = sunhpc.version_micro
self.getopt = sunhpc.core.utils.Struct()
self.getopt.s = [ 'h' ]
self.getopt.l = [ 'help',
'list-rcfiles',
'list-project-info',
'rcfile='
]
# Unset our local
try:
os.environ["LANG"]
except KeyError:
pass
def run(self):
sys.exit(-1)
def projectInfo(self):
return [ self.projectName,
self.projectVersionName,
int(self.projectVersionMajor),
int(self.projectVersionMinor),
int(self.projectVersionMicro) ]
def getArgs(self):
return self.args
def setArgs(self, argslist):
self.args = argslist
def parseArgs(self, rcbase=None):
"""Parses the command line arguments and all the relevant
resource-control (RC) files for this application. The usage_command
(generally argv[0]) will determine which the name of our rcfile,
unless overrided with the rcbase argument."""
# Save any existing options
args = self.getArgs()
# First pass to get rcfiles specified on the cmd line
self.setArgs(self.caller_args)
self.parseCommandLine(rcfile=1)
# Parse Resource Control files
self.setArgs([])
if not rcbase:
rcbase = self.usage_command
self.parseRC(rcbase)
for rc in self.rcForce:
self.parseRCFile(rc, rcbase)
# Command line options always win
self.setArgs(args + self.args + self.caller_args)
self.parseCommandLine()
def parseRC(self, rcbase, section=None):
rcfile = rcbase + 'rc'
if not section:
section = rcbase
# Where we look for resource-control files. First in
# the default 'etc' location, then HOME, finally in this dir.
# We use data from all three, such that later rc files take
# precedence.
dirList = [ os.path.join(os.sep,'opt', self.projectName, 'etc') ]
if 'HOME' in os.environ:
dirList.append(os.environ['HOME'])
dirList.append('.')
# Look for both hidden and visible rc files.
for dir in dirList:
self.parseRCFile(os.path.join(dir, '.' + rcfile), section)
self.parseRCFile(os.path.join(dir, rcfile), section)
def parseRCFile(self, filename, section):
if os.path.isfile(filename) and filename not in self.rcfileList:
self.rcfileList.append(filename)
file = open(filename, 'r')
parser = make_parser()
handler = self.rcfileHandler(self)
if section:
handler.setSection(section)
parser.setContentHandler(handler)
try:
parser.parse(file)
except SAXParseException as msg:
print (filename, "XML parse exception: ", msg)
file.close()
def parseCommandLine(self, rcfile=0):
"""Calls getopt to parse the command line flags. In
rcfile mode we just get --rcfile options."""
short = ''
for e in self.getopt.s:
if isinstance(e, tuple):
short = short + e[0]
else:
short = short + e
long = []
for e in self.getopt.l:
if isinstance(e, tuple):
long.append(e[0])
else:
long.append(e)
try:
opts, args = getopt.getopt(self.args, short, long)
except getopt.GetoptError as msg:
sys.stderr.write("error - %s\n" % msg)
self.usage()
sys.exit(1)
for c in opts:
if rcfile:
if c[0] != "--rcfile":
continue
self.parseArg(c)
if not rcfile:
self.args = args
def parseArg(self, c):
if c[0] in ('-h', '--help'):
self.help()
sys.exit(0)
elif c[0] == '--list-rcfiles':
print (self.rcfileList)
sys.exit(0)
elif c[0] == '--list-project-info':
print (self.projectInfo())
sys.exit(0)
elif c[0] == '--rcfile':
self.rcForce.append(c[1])
else:
return 0
return 1
def usage(self):
if 'COLUMNS' in os.environ:
cols = os.environ['COLUMNS']
else:
cols = 80
usagelist = [ 'Usage: ', self.usage_command, ' ' ]
# Build string of argument-free short options.
s = '[-'
for e in self.getopt.s:
if len(e) == 1:
s = s + e
s = s + ']'
if len(s) == 3:
s = ''
usagelist.append(s)
# Add the argument short options to the above string
for e in self.getopt.s:
if isinstance(e, tuple):
v = e[0]
h = e[1]
else:
v = e
h = 'arg'
if len(v) != 1:
usagelist.append(' [-' + v[:-1] + ' ' + h + ']')
# Add argument-free long options
for e in self.getopt.l:
if isinstance(e, tuple):
v = e[0]
else:
v = e
if v[len(v)-1] != '=':
usagelist.append(' [--' + v + ']')
# Add argument long options
for e in self.getopt.l:
if isinstance(e, tuple):
v = e[0]
h = e[1]
else:
v = e
h = 'arg'
if v[len(v)-1] == '=':
usagelist.append(' [--' + v[:-1] + ' ' + h + ']')
usagelist.append(self.usageTail())
# Print the usage, word wrapped to the correct screen size.
print (self.usage_name, '- version', self.usage_version)
l = 0
s = ''
for e in usagelist:
if l + len(e) <= cols:
s = s + e
l = l + len(e)
else:
print (s)
l = len(e)
s = e
if s:
print (s)
def help(self):
self.usage()
def usageTail(self):
return ''
def getArch(self):
return sunhpc.core.utils.getNativeArch()
class RCFileHandler(sunhpc.core.utils.ParseXML):
def __init__(self, application):
sunhpc.core.utils.ParseXML.__init__(self, application)
self.foundSection = 0
self.section = self.app.usage_command
def setSection(self, section):
self.section = section
def startElement(self, name, attrs):
#
# need to convert all the attributes to ascii strings.
# starting in python 2, the xml parser puts the attributes in
# unicode which causes problems with sunhpc apps classes, specifically
# those that append path names found in the attributes to the sys.path
#
newattrs = {}
for (aname, avalue) in attrs.items():
newattrs[aname] = str(attrs[aname])
if self.foundSection:
sunhpc.core.utils.ParseXML.startElement(self, name, newattrs)
elif name == self.section:
self.startElementSection(name, newattrs)
def endElement(self, name):
if self.foundSection and name == self.foundSection:
self.endElementSection(name)
if self.foundSection:
sunhpc.core.utils.ParseXML.endElement(self, name)
def getOptions(self):
return self.options
# <section parent="base">
def startElementSection(self, name, attrs):
parent = attrs.get('parent')
if parent:
self.app.parseRC(parent, parent)
self.foundSection = 1
def endElementSection(self, name, attrs):
self.foundSection = 0
# <usage>
def startElement_usage(self, name, attrs):
usageName = attrs.get('name')
usageVersion = attrs.get('version')
if usageName:
self.app.usage_name = usageName
if usageVersion:
self.app.usage_version = usageVersion
# <option>
def startElement_option(self, name, attrs):
argName = attrs.get('name')
# Will return None if value is not present.
argValue = attrs.get('value')
list = self.app.getArgs()
if len(argName) > 1:
flag = '--' + argName
# We differentiate between empty values and
# no value at all.
if argValue is not None:
list.append('%s=%s' % (flag, argValue))
else:
list.append(flag)
else:
flag = '-' + argName
if argValue:
list.append('%s %s' % (flag, argValue))
else:
list.append(flag)
self.app.setArgs(list)
# <project>
def startElement_project(self, name, attrs):
self.app.projectName = attrs.get('name')
self.app.projectVersionName = attrs.get('versionName')
self.app.projectVersionMajor = attrs.get('versionMajor')
self.app.projectVersionMinor = attrs.get('versionMinor')
self.app.projectVersionMicro = attrs.get('versionMicro')

View File

@@ -2,9 +2,11 @@
import sunhpc
import sunhpc.core
import sunhpc.core.ip
import sunhpc.core.app
import sunhpc.core.sql
import sunhpc.core.dist
import sunhpc.core.files
import sunhpc.core.build
import sunhpc.core.utils
import sunhpc.core.security
import sunhpc.core.partition

46
sbin/check-port Executable file
View File

@@ -0,0 +1,46 @@
#!/opt/sunpy3/bin/python3
import os
import sys
import socket
import sunhpc.invoke
class App(sunhpc.core.app.Application):
def __init__(self, argv):
sunhpc.core.app.Application.__init__(self,argv)
self.usage_name = 'Check Port'
self.usage_version = '4.2'
self.node_name = 'localhost'
self.port_num = 5901
nodehelp = '(nodename default=%s)' % self.node_name
porthelp = '(port number default=%d)' % (self.port_num)
self.getopt.l.extend([ ('node=',nodehelp),('port=',porthelp) ])
self.getopt.s.extend([('n:',nodehelp),('p:',porthelp)])
def parseArg(self, c):
sunhpc.core.app.Application.parseArg(self,c)
key, val = c
if key in ('--port'):
self.port_num = int(val)
elif key in ('--node'):
self.node_name = val
def run(self):
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.connect((self.node_name,self.port_num))
except:
print ('Port(%s) is closed' % self.port_num)
sys.exit(1)
print ('Port(%s) is open' % self.port_num)
s.close()
sys.exit(0)
app = App(sys.argv)
app.parseArgs()
app.run()