文本自动对齐功能探索实现
发布日期:2021-06-30 10:11:39 浏览次数:4 分类:技术文章

本文共 4680 字,大约阅读时间需要 15 分钟。

自动对齐的支持:
思路:
目前想到的是简单地保存前缀空格和,根据语句与当前空格和预测下一行空格和。

if elif else endif 支持

例如遇到If下一行预测就是前缀加一个tab大小的空格,而elif ,else ,endif则无法使用预测的前缀空格,因为他们要特殊地和对应的if对齐,所有要保存之前所有遇到if的前缀队列,对齐的空格数直接使用最后一次保存的值。

而预测给当前的值直接赋值给下一行预测,需要注意的是注意结束标志endif则需要将预测的值减去一个tab赋给下一行的预测。

这样就完成了if的自动对齐。

for

支持就需要在之前的if支持的机制之上进行。

但是for只需要end_for就可以,同理更简单了,只需要遇到for,添加当前的前缀到for的队列,然后下一行预测添加一个tab大小的空格,endif直接使用最后一个for队列的前缀空格,下一行进行减一个tab就可以。

while 同理,也只是有一个end_while。
repeat 同理,含有until和end_repeat两个对应的key。

case

ELSE和END_CASE有一个比较麻烦的点,ELSE在if语法有相同的Key,这里就需要进行判断ELSE是属于哪一个的才能选择正确的前缀。

这里可能需要在数据结构中添加一个记录if和case当前没有结束(没有对应的end_if和end_case)的缓存队列,其中保存行号,ELSE匹配if与case最近(较大)的行号。

 

示例代码:

def GetAutoAlignment(self, spaceCount, content):        """        自动对齐功能标准的是需要分析器,本函数是其简化        :param preSpace:         :param content:         :return:         """        currentSpace = spaceCount        lineCount = 0        nextSpace = currentSpace        newContent = []        word = []        tabSize = 4        keyDict = {"IF":[], "FOR":[], "WHILE":[], "REPEAT":[], "CASE":[]}        countDict = {"IF":[0,[]], "FOR":[0,[]], "WHILE":[0,[]], "REPEAT":[0,[]], "CASE":[0,[]]}        middleDict = {"ELSIF":"IF","END_IF":"IF",                      "END_FOR":"FOR",                      "END_WHILE":"WHILE",                      "UNTIL":"REPEAT","END_REPEAT":"REPEAT",                      "END_CASE":"CASE"}        specialMiddleDict = {"ELSE":["IF","CASE"]}        endList = ["END_IF","END_FOR","END_WHILE","END_REPEAT","END_CASE"]        for line in content.split("\n"):            lineCount += 1            for i in (line+"\n"):                if i in [" ", "\n", ";", "("]:                    tempword = "".join(word).upper()                    word = []                    if tempword == "":                        continue                    if tempword in keyDict:                        keyDict[tempword].append(lineCount)                        if tempword in countDict:                            countDict[tempword][0] += 1                            countDict[tempword][1].append(currentSpace)                            nextSpace = currentSpace + tabSize                    elif tempword in middleDict:                        if countDict[middleDict[tempword]][0] != 0:                            tempSpace = countDict[middleDict[tempword]][1][-1] #不能立马赋值到currentSpace,影响下面赋值                            if tempword in endList:                                countDict[middleDict[tempword]][0] -= 1                                countDict[middleDict[tempword]][1].pop(-1)                                keyDict[middleDict[tempword]].pop(-1)                                nextSpace = currentSpace - tabSize                            currentSpace = tempSpace                    elif tempword in specialMiddleDict:  #ELSE匹配最近的IF或者CASE                        recentSkey = ""                        recentNumber = 0                        for Skey in specialMiddleDict[tempword]:                            if keyDict[Skey] != []:                                if recentSkey == "":                                    recentSkey = Skey                                    recentNumber = keyDict[Skey][-1]                                else:                                    if recentNumber < keyDict[Skey][-1]:                                        recentSkey = Skey                        if recentSkey!= "" and countDict[recentSkey][0] != 0:                            currentSpace = countDict[recentSkey][1][-1]                    break                else:                    word.append(i)            line = " "*currentSpace + line.lstrip()            newContent.append(line)            currentSpace = nextSpace        return "\n".join(newContent)    def OnAutoAlignment(self):        content = self.Editor.GetSelectedText()        startPos = self.Editor.GetSelectionStart()        endPos = self.Editor.GetSelectionEnd()        preSpace = ""        for i in range(0,self.Editor.GetLineCount()):            if self.Editor.GetLineSelEndPosition(i) >= startPos:                lineContent = self.Editor.GetLineText(i-1)                space = []                for j in lineContent:                    if j == " ":                        space.append(" ")                    else:                        preSpace = "".join(space)                        break                break        self.Editor.ReplaceSelection(self.GetAutoAlignment(len(preSpace),content))

有些可能需要自动换行:

keyList = ["OF","THEN","ELSE","END_IF;","END_CASE;","DO","EXIT;","END_FOR;",                   "END_WHILE;","REPEAT","UNTIL","END_REPEAT;"]        reContent = "|".join(keyList)        newContent = re.sub(r"(%s)([ ]*)([^\n])"%(reContent),r"\1\n\3",content)

 

转载地址:https://islet.blog.csdn.net/article/details/117261976 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:OpenPLC 常规变量类型大小范围
下一篇:Node-RED opcua items 二次修改记录

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月16日 13时25分24秒