def MakeCmdNodesLink(self, arg_oNodeArray=None): if (None == arg_oNodeArray) or (1 == VOS.Len(arg_oNodeArray)): return else: for i, oNode in enumerate(arg_oNodeArray): if (VOS.Len(arg_oNodeArray) - 1) != i: oNode.m_oSubNode = arg_oNodeArray[i + 1] return
def BackspaceDisplay(self): VOS.PutCh(b'\b') VOS.PutCh(b' ') VOS.PutCh(b'\b') sys.stdout.flush() if (None != self.m_strCurrentLine) and (1 <= VOS.Len(self.m_strCurrentLine)): self.m_strCurrentLine = self.m_strCurrentLine[:-1] return
def ExecStringOut(self, arg_strText, arg_iTextColor = VOS.FOREGROUND_DARKWHITE, arg_iBackgroundColor = VOS.FOREGROUND_BLACK): iRetCode, strLine = VOS.ExecStringOut(arg_strText, arg_iTextColor, arg_iBackgroundColor) if None == iRetCode: self.m_strCurrentLine += strLine else: self.m_strCurrentLine = strLine return
def KeywordMaxCompare(self, arg_strSegment=None): if None == arg_strSegment: return NO_MATCHING, None #假設節點為display #displayaaa elif VOS.Len(arg_strSegment) > VOS.Len(self.m_strKeyword): return NO_MATCHING, None #display elif arg_strSegment == self.m_strKeyword: return MATCHING_ON, self.m_strKeyword #disp elif arg_strSegment == self.m_strKeyword[0:VOS.Len(arg_strSegment)]: return PARTLY_MATCHING, self.m_strKeyword #asdf else: return NO_MATCHING, None
def CharInputRealTimeProc(self, arg_cCh = ' '): self.m_strRawCmd += arg_cCh #第一行and第三行:_或_ _ #第二行and第三行:d_ _ if (((None == self.m_strCmd) or (0 == VOS.Len(self.m_strCmd))) or \ ' ' == self.m_strCmd[-1]) \ and (' ' == arg_cCh): if None == self.m_ostkCmd: self.m_ostkCmd = CCmdNodesStack() self.m_ostkCmd.Push(CCmdStkNode.CMDSTK_Node(arg_Attribute = "SPACE", arg_cCh = ' ')) return #普通字符和非連續的空格、非頭部的空格追加(連續的空格不追加、頭部的空格不追加) if (' ' != arg_cCh) or \ ((' ' == arg_cCh) and \ #未完工 这里错了,如果输入的时空格,不能随便追加,需要匹配后追加,万一能匹配关键字呢? ((0 < VOS.Len(self.m_strCmd)) and (' ' != self.m_strCmd[-1]))): self.m_strCmd += arg_cCh #如果此時的m_strCmd最後一個字符時空格,考慮如下情況: #display ip routing-table _ 有效命令 #display ip asdf _ 無效命令 #那麼空格前的關鍵字都已經做過了處理,這裡直接返回即可 #輸入的是空格,就可能被追加到m_strCmd中(非連續空格),那麼它僅是第一個空格,就不必返回 if (' ' == self.m_strCmd[-1]) and (' ' != arg_cCh): return #空格、普通字符模式:得到最後的一個關鍵字(其實是最後一個關鍵字的片段),即display ip rou中的rou KeywordsArray = self.m_strCmd.split(' ') #非連續空格輸入時,m_strCmd == “display ip_”,因此KeywordsArray[-1] == '' strSegment = (KeywordsArray[-1] if '' != KeywordsArray[-1] else KeywordsArray[-2]) self.ProcessKeyword(strSegment, arg_cCh) #不論匹配與否,都有節點被壓棧了 if ' ' == arg_cCh: self.m_ostkCmd.Pop() self.m_ostkCmd.Push(CCmdStkNode.CMDSTK_Node(arg_Attribute = "SPACE", arg_cCh = arg_cCh)) self.DisplayProcess(arg_cCh) return
def CmdFormat(self, arg_strCmd, arg_iPortal = "BACKSPACE_FIRST_WAY"): if None == arg_strCmd: arg_strCmd = self.m_strCmd if 0 == VOS.Len(arg_strCmd): return if ' ' == arg_strCmd[-1]: return #命令行未補齊是不會有空格或tab了 arg_strCmd = arg_strCmd.strip() if 0 == VOS.Len(arg_strCmd): return #分析標準命令行 KeywordsArray = self.m_strCmd.split(' ') if 0 == VOS.Len(KeywordsArray[-1]): KeywordsArray.pop() #分析屏幕命令行關鍵字之間的空格數 iSpaceArray = self.GetDisplaySpace(KeywordsArray) self.ClearCurrentLine() iLen = VOS.Len(KeywordsArray) for i, strSegment in enumerate(KeywordsArray): if 0 == VOS.Len(strSegment): continue if 0 == i: iRetCode, strKeyword = self.ProcessKeyword(strSegment, "BACKSPACE_FIRST_WAY") #最後一個關鍵字分析後,節點不壓棧 elif (iLen - 1) == i: iRetCode, strKeyword = self.ProcessKeyword(strSegment, "NORMALCHAR_WAY") else: iRetCode, strKeyword = self.ProcessKeyword(strSegment, "BACKSPACE_NONFIRST_WAY") self.DisplayProcess(iRetCode, strKeyword, strSegment, "BACKSPACE_FIRST_WAY", iSpaceArray[i]) return
def BackspaceInput(self): #都刪空了就直接返回 if 0 == VOS.Len(self.m_strCurrentLine): return #只要刪除的時空格,就無需觸發關鍵字重搜索 if 1 <= VOS.Len(self.m_strCurrentLine) and ' ' == self.m_strCurrentLine[-1]: #如果是最後一個空格,如y _,還要刪除m_strCmd裡的 if 2 <= VOS.Len(self.m_strCurrentLine) and \ ' ' == self.m_strCurrentLine[-1] and \ ' ' != self.m_strCurrentLine[-2]: self.m_strCmd = self.m_strCmd[:-1] self.BackspaceDisplay() return self.m_strCmd = self.m_strCmd[:-1] self.BackspaceDisplay() self.CmdFormat(self.m_strCmd, "BACKSPACE_FIRST_WAY") #只有從getch()返回的才需要寫成b' '的形式 return
def Run(self): bQuit = False #命令行總循環 while True: #關鍵字匹配循環 while True: cRawCh = VOS.GetCh() if b'\t' == cRawCh: #tab cRawCh = b' ' if b'\r' == cRawCh: #回車 self.m_strCurrentLine = '' self.CmdFormatRealTime() self.ExecStringOut(arg_strText = '\nstrCmd = \"' + self.m_strCmd + '\"\n', arg_iTextColor = VOS.FOREGROUND_YELLOW) if None != self.m_ostkCmd: self.m_ostkCmd.PopAll() break elif cRawCh == b'\b': #退格 self.BackspaceInput() elif cRawCh == b' ': #空格 self.SpaceTabInput() elif cRawCh == b'\xE0': #向上 self.ExecStringOut("向上") elif cRawCh == b'\x50': #向下 self.ExecStringOut("向下") elif cRawCh == b'\x1B': #ESC bQuit = True break #普通字符,如a #彩色版本可變換顏色,以實時標記鍵入情況,故關鍵字匹配改為實時觸發 else: #VOS.PutCh(cRawCh) #實時觸發 #self.m_strCurrentLine += cRawCh.decode() self.CharInputRealTimeProc(cRawCh.decode()) #self.CmdFormatRealTime("NORMALCHAR_WAY") if True == bQuit: break #執行命令,未完工 self.m_strCmd = '' return
def GetLastSegmentLen(self): if None == self.m_oList: return None oList = copy.deepcopy(self.m_oList) strSegment = '' iCount = 0 for i in range(VOS.Len(oList)): if "SPACE" == self.Top(oList).GetAttribute(): if(0 < i): break else: self.Pop(oList) continue oNode = self.Pop(oList).GetCmdNode() if None != oNode: iCount += 1 return iCount
def FormatKeywordDisplay(self, strSegment, strKeyword): if 0 == VOS.Len(strKeyword): return #刪除已鍵入的關鍵字片段 for Letter in strSegment: self.BackspaceInput() #著色打印完整關鍵字 VOS.set_cmd_text_color(VOS.FOREGROUND_GREEN) for Letter in strKeyword: VOS.PutCh(str.encode(Letter)) VOS.resetColor() #不用加空格,用戶的空格命令行還沒加 return
def GetDisplaySpace(self, arg_KeywordArray): iSpaceArray = list() cPreChar = None for i, cCh in enumerate(self.m_strCurrentLine): if (None == cPreChar and ' ' != cCh) or (' ' == cPreChar and ' ' != cCh): iSpaceArray.append(i) cPreChar = cCh for i, iPosition in enumerate(iSpaceArray): if 0 == i: continue iPrevCharNum = 0 for j in range(i + 1): if 0 == j: continue iPrevCharNum += (iSpaceArray[j - 1] + VOS.Len(arg_KeywordArray[j - 1])) iSpaceArray[i] -= iPrevCharNum return iSpaceArray
def ProcessKeyword(self, arg_strSegment, arg_cCh): if 0 == VOS.Len(arg_strSegment): return ERROR, None if None == self.m_ostkCmd: oLastNode = None else: oStkNode = self.m_ostkCmd.Top() if None == oStkNode: oLastNode = None else: if (None != oStkNode) and ("SPACE" == oStkNode.GetAttribute()): oStkNode = self.m_ostkCmd.GetElement(-2) oLastNode = (None if None == oStkNode else oStkNode.GetCmdNode()) else: oLastNode = None #最大匹配 iRetCode, strKeyword, oNode = self.KeywordMaxMatching(oLastNode, arg_strSegment) if None == self.m_ostkCmd: self.m_ostkCmd = CCmdNodesStack() #精確匹配上 或 部分唯一匹配上,這裡不區分 #精確匹配上的,不存在剩餘部分,所以無需追加 #唯一但非精確匹配上的,如disp if SOLE_MATCHING_ON == iRetCode: self.m_ostkCmd.Push(CCmdStkNode.CMDSTK_Node(oNode, "SOLE MATCHING ON", arg_cCh)) return SOLE_MATCHING_ON, strKeyword if MULTI_MATCHING_ON == iRetCode: self.m_ostkCmd.Push(CCmdStkNode.CMDSTK_Node("MULTI MATCHING ON", arg_cCh)) return MULTI_MATCHING_ON, None #走到這就是沒匹配上,壓入空節點 self.m_ostkCmd.Push(CCmdStkNode.CMDSTK_Node(oNode, "NO MATCHING", arg_cCh)) #self._PrintStk() return NO_MATCHING, None
def RegCmd(self, arg_strCmd, arg_strHelpInfo, arg_fCmdProc): oNodeArray = [] oKeywordArray = arg_strCmd.split(' ') #準備待註冊命令的節點串 for strKeyword in oKeywordArray: #新建一個節點 #strKeyword裡可能帶有$、[]等等特殊標識,由Node處理 if 0 < VOS.Len(strKeyword): oNode = CNode.CMD_Node(arg_strKeyword=strKeyword) oNodeArray.append(oNode) #串接起來 self.MakeCmdNodesLink(oNodeArray) def AppendCmdProc(arg_oNodeArray=None, arg_fCmdProc=None): if (None == arg_oNodeArray) or (None == arg_fCmdProc): return def GetLastRequiredNode(arg_oNodeArray=None): for oNode in reversed(arg_oNodeArray): if True == oNode.IsRequired(): return oNode return #獲取最後一個必填節點 oNode = GetLastRequiredNode(arg_oNodeArray) if None != oNode: oNode.m_fCmdProc = arg_fCmdProc return #加上回調函式 AppendCmdProc(oNodeArray, arg_fCmdProc) self.Insert(oNodeArray) return
def GetLastKeywordNo(self, arg_strCmd): KeywordsArray = arg_strCmd.split(' ') return VOS.Len(KeywordsArray)