#-*- coding: utf-8 -*- #Copyright 2008 Calculate Pack, http://www.calculate-linux.ru # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. Version = "calculate-server 0.0.1" import sys sys.path.append('/var/tmp/calculate2/calculate-lib/trunk/pym') import cStringIO import cl_base import struct import termios import fcntl import cl_utils pcs = cl_utils.prettyColumnStr class cl_help: """Объект для работы со справкой, и обработкой параметров. Конструктор __init__ должен определить следующие переменные: self.chapter список разделов справки, каждый элементы состоит из имени раздела, флаг видимый/скрытый, кол-во переводов строк после названия раздела, количество строк после раздела, тип раздела Пример: [("Copyright",False,0,2),"options"] self.relService словарь связей сервисов и действующих опций ключ - название сервиса, значение - список отображаемых разделов отмеченных как "options" Пример: {"samba":[_("Common options"), _("Service Samba options")]} self.relOptions словарь связей длинных опций помощи и выводимых разделов помощи с опциями ключ - параметр справки, значение список отображаемых разделов справки Пример: {"help-ldap":[_("Common options"), _("Service LDAP options)]} self.progName словарь имена используемых программ и их номера для доступа к переменным Пример: {'cl-groupadd':0, 'cl-groupdel':1} self.data список данных для словаря, каждый эленмент словарь: progAccess: список номеров программ отображающих Пример: {'progAccess':(0,), 'shortOption':"g", 'longOption':"gid", 'optVal':"GID", 'helpChapter':_("Options"), 'help':_("use GID for the new group") }, после заполнения параметров необходимо выполнить self._cl_help__setParamHelp() для заполнения справки """ def __init__(self, cmdName): # ширина консоли взята 80 # -1 чтобы компенсировать расстрояние между колонками self.consolewidth = 79 self.column_width = 32 self.cmdName = cmdName #короткие опции командной строки self.shortOpt = [] #длинные опции командной строки self.longOpt = [] #optEnd = "" #if "user" in self.cmdName and not "mod" in self.cmdName: #optEnd = _("user") #elif "group" in self.cmdName and not "mod" in self.cmdName: #optEnd = _("group") #self.__setParamHelp() def getChapterNumber(self,NameChapter): # Показать номер раздела по его имени num = 0 for i in self.chapter: if i[0] == NameChapter: return num num += 1 return False def __setParamHelp(self): # сформировать нужное количество блоков раздела self.chapterBloc = [""]*len(self.chapter) # записать параметры в справку sp = [] for par in self.data: if par.has_key("shortOption"): if self.access(par): sp.append(par["shortOption"]) elif par.has_key("longOption"): if self.access(par): sp.append(par["longOption"]) #sp.sort() for shortOption in sp: for par in self.data: if par.has_key("shortOption") and self.access(par): if par["shortOption"] == shortOption: numChapter = self.getChapterNumber(par['helpChapter']) if par.has_key("longOption"): if par.has_key("optVal"): longOption = par["longOption"] + " " +\ par["optVal"] else: longOption = par["longOption"] helpTxt = pcs( " -%s, --%s "%(par["shortOption"],longOption), self.column_width, par['help'], self.consolewidth-self.column_width) else: helpTxt = pcs( " -%s "%(par["shortOption"]), self.column_width, par['help'], self.consolewidth-self.column_width) self.addChapterHelp(numChapter,helpTxt) break elif par.has_key("longOption") and self.access(par): if par["longOption"] == shortOption: numChapter = self.getChapterNumber(par['helpChapter']) longOption = par["longOption"] helpTxt = pcs( " --%s "%(longOption), self.column_width, par['help'], CONWIDTH-self.column_width) self.addChapterHelp(numChapter,helpTxt) break for par in self.data: if not (par.has_key("shortOption") or\ par.has_key("longOption")) and\ self.access(par): helpTxt = par['help'] numChapter = self.getChapterNumber(par['helpChapter']) self.addChapterHelp(numChapter,helpTxt) def getHelp(self, optionsChapters=False): # Выдать справку help = "" for numChapter in range(len(self.chapter)): chapter = self.chapter[numChapter] typeChapter = chapter[4] nameChapter = chapter[0] if optionsChapters and typeChapter=="options": if not (nameChapter in optionsChapters): continue visibleChapter = chapter[1] beforeStrChapter = chapter[2] afterStrChapter = chapter[3] bef = "" for i in range(beforeStrChapter): bef += "\n" aft = "" for i in range(afterStrChapter): aft += "\n" if visibleChapter: help += nameChapter + ": " + bef help += self.chapterBloc[numChapter] + aft return help.encode("UTF-8") def addChapterHelp(self, numChapter, helpTxt): # Добавить в раздел помощи numChapteк тектстовую строку helpTxt self.chapterBloc[numChapter] += helpTxt return True def addData(self,dataHash): # На будущее (добавляет опции) self.data.append(dataHash) return True def access(self,dataHash): # доступна ли опция вызывающей программе numProg = self.progName[self.cmdName] if dataHash.has_key('progAccess'): if numProg in dataHash['progAccess']: return True else: return False else: return True def getTypeChapter(self, nameChapter): """Показать тип раздела по его имени""" flagFind = False for numChapter in range(len(self.chapter)): chapter = self.chapter[numChapter] name = chapter[0] if nameChapter == name: typeChapter = chapter[4] flagFind = True break if flagFind: return typeChapter else: return False def clearAllOpt(self): if len(self.shortOpt) > 0: self.shortOpt = [] if len(self.longOpt) > 0: self.longOpt = [] return True def getAllOpt(self,typeOpt="short", optionsChapters=False): # Выдать все действующие опции if typeOpt=="short": if len(self.shortOpt) == 0: for par in self.data: if optionsChapters and\ self.getTypeChapter(par['helpChapter'])=="options": if not (par['helpChapter'] in optionsChapters): continue if par.has_key("shortOption") and self.access(par): if par.has_key("optVal"): self.shortOpt.append(par["shortOption"]+':') else: self.shortOpt.append(par["shortOption"]) return "".join(self.shortOpt) if typeOpt=="long": if len(self.longOpt) == 0: for par in self.data: if optionsChapters and\ self.getTypeChapter(par['helpChapter'])=="options": #print par["longOption"] if not (par['helpChapter'] in optionsChapters): continue if par.has_key("longOption") and self.access(par): if par.has_key("optVal"): self.longOpt.append(par["longOption"]+'=') else: self.longOpt.append(par["longOption"]) return self.longOpt def getShortOpt(self,option): # Из любой опции получаем короткую опцию for par in self.data: if par.has_key("shortOption") and self.access(par): if (par.has_key("longOption") and\ par["longOption"] == option) or \ par["shortOption"] == option: return par["shortOption"] break return "" class cl_smartcon(object): selfobj = None def __new__(cls, *args,**kw): """Механизм синглтона""" if cls.selfobj is None: cls.selfobj = object.__new__(cls,*args,**kw) return cls.selfobj def getconsolewidth(self): """Получить ширину текущей консоли""" s = struct.pack("HHHH", 0, 0, 0, 0) fd_stdout = sys.stdout.fileno() x = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, s) #(rows, cols, x pixels, y pixels) return struct.unpack("HHHH", x)[1] def printRight(self, offsetLeft, offsetRight): """Добавляет необходимое количество пробелов: количество пробелов = (ширина консоли - offsetLeft - offsetRight) """ cols = self.getconsolewidth() for i in range(cols - offsetLeft - offsetRight): sys.stdout.write(" ") def colorPrint(self,attr,fg,bg,string): """Раскрашивает выводимое сообщение Параметры: attr - это атрибут fg - цвет символа bg - цвет фона в случае если параметр равен "" то он не изменяется attr может принимать следующие значения: 0 сбросить все атрибуты (вернуться в нормальный режим) 1 яркий (обычно включает толстый шрифт) 2 тусклый 3 подчёркнутый 5 мигающий 7 реверсный 8 невидимый fg может принимать следующие значения: 30 чёрный 31 красный 32 зелёный 33 жёлтый 34 синий 35 фиолетовый 36 голубой 37 белый bg может принимать следующие значения: 40 чёрный 41 красный 42 зелёный 43 жёлтый 44 синий 45 фиолетовый 46 голубой 47 белый """ lst = [] if attr: lst.append(attr) if fg: lst.append(fg) if bg: lst.append(bg) sys.stdout.write("\033[%sm%s\033[0m" %(";".join(lst),string)) def redBrightPrint(self, string): """Печатает яркое красное сообщение""" self.colorPrint("1","31","",string) def greenBrightPrint(self, string): """Печатает яркое зеленое сообщение""" self.colorPrint("1","32","",string) def yellowBrightPrint(self, string): """Печатает яркое желтое сообщение""" self.colorPrint("1","33","",string) def blueBrightPrint(self, string): """Печатает яркое cинее сообщение""" self.colorPrint("1","34","",string) def lenString(self, string): """Получаем длинну строки""" stringUnicode = cl_utils._toUNICODE(string) lenString = len(stringUnicode) return lenString def defaultPrint(self, string): sys.stdout.write(string) sys.stdout.flush() def printLine(self, argL, argR): """Печатает справа и слева консоли цветные сообщения""" #Допустимые цвета colorDict = {\ # цвет по умолчанию '':self.defaultPrint, # ярко зеленый 'greenBr':self.greenBrightPrint, # ярко голубой 'blueBr':self.blueBrightPrint, # ярко красный 'redBr':self.redBrightPrint, # ярко желтый 'yellowBr':self.yellowBrightPrint, } # cмещение от левого края консоли offsetL = 0 for color,leftString in argL: offsetL += self.lenString(leftString) if colorDict.has_key(color): # печатаем и считаем смещение colorDict[color](leftString) else: colorDict[''](leftString) # cмещение от правого края консоли offsetR = 0 for color,rightString in argR: offsetR += self.lenString(rightString) # Добавляем пробелы self.printRight(offsetL, offsetR) for color,rightString in argR: if colorDict.has_key(color): # печатаем и считаем смещение colorDict[color](rightString) else: colorDict[''](rightString) print "" def printNotOK(self, string): """Вывод на печать в случае сбоя""" self.printLine((('greenBr',' * '), ('',string), ), (('blueBr','['), ('redBr',' !! '), ('blueBr',']'), ) ) def printOK(self, string): """Вывод на печать в случае успеха""" self.printLine((('greenBr',' * '), ('',string), ), (('blueBr','['), ('greenBr',' ok '), ('blueBr',']'), ) ) def printWARNING(self, string): """Вывод на печать предупреждения""" self.printLine((('yellowBr',' * '), ('',string), ), (('',''), ) ) def printERROR(self, string): """Вывод на печать предупреждения""" self.printLine((('redBr',' * '), ('',string), ), (('',''), ) ) def printSUCCESS(self, string): """Вывод на печать в случае успеха без [ok] справа""" self.printLine((('greenBr',' * '), ('',string), ), (('',''), ) )