Latex编辑功能的简陋实现

功能说明

修改操作

\modify {Origin text} {Modification}
效果
Origin text  Modification

删除操作

\delete{Delete}
效果
Delete

插入操作

\addtext{Add Something}
效果
Add Something

确认修改(消除编辑标记)

python CommitModify.py path-to-tex-file

特色

支持嵌套式的编辑,如
\modify{\addtext{old text}}{\delete{some words} and more}

缺陷

命令不能跨行,如下为非法命令
\modify{Old Text}
{New Text}

实现方式

在latex文件开头加入如下代码
\usepackage{xcolor}
\usepackage{mathrsfs}
\def\sharedaffiliation{ \end{tabular} \begin{tabular}{c}}
\usepackage{enumerate}
\usepackage[normalem]{ulem} 
\newcommand{\modify}[2]{\sout{#1} \textcolor{red}{#2}}
\newcommand{\addtext}[1]{\textcolor{red}{#1}}
\newcommand{\delete}[1]{\sout{#1}}

编辑确认的python脚本
#! /bin/python

def getBrace(line, index=0):
    '''
    find the index of out brace in a line
    {{{}}},0 -> return (0,5)
    {{{}}},1 -> return (1,4) 
    '''
    si = -1
    ei = -1
    cnt = 0
    while index < len(line):
        if line[index] == '{':
            if cnt == 0:
                si = index
            cnt = cnt + 1
        elif line[index] == '}':
            cnt = cnt - 1;
            if cnt < 0:
                return (-1, -1)
            elif cnt == 0:
                ei = index
                break
        index = index + 1    
    return (si, ei)

def replace_modify(line):
    '''
    replace \modify{arg1}{arg2} commands
    '''
    while True:
        index = line.find('''\modify''')
        if index == -1: break
        s1, e1 = getBrace(line, index)
        if e1 == -1: break
        s2, e2 = getBrace(line, e1+1)
        print line[index:e2+1]
        line = line[0:index] + line[s2+1:e2] + line[e2+1:]
    return line

def replace_delete(line):
    '''
    replace \delete{arg1} commands
    '''
    while True:
        index = line.find('''\delete''')
        if index == -1: break
        s1, e1 = getBrace(line, index)
        if e1 == -1: break
        print line[index:e1+1]
        line = line[0:index] + line[e1+1:]
    return line

def replace_insert(line):
    '''
    replace \addtext{arg1} commands
    '''
    while True:
        index = line.find('''\\addtext''')
        if index == -1: break
        s1, e1 = getBrace(line, index)
        if e1 == -1: break
        print line[index : e1+1]
        line = line[0:index] + line[s1+1:e1] + line[e1+1:]
    return line

if __name__ == '__main__':
    import os, sys
    if len(sys.argv) <= 1:
        print "Usage : CommitModify tex-file-name"
        sys.exit()
    fpath = sys.argv[1]
    
    if not os.path.isfile(fpath):
        print fpath + "Not Found"
        sys.exit()
        
    if not os.path.splitext(fpath)[1] == '.tex':
        print fpath + "Not A Tex File"
        sys.exit()
        
    h = lambda l: replace_modify(replace_delete(replace_insert(l))) 
    f = open(fpath, 'r')
    try:
        buffer = [h(l) for l in f.readlines()]
    finally:
        f.close()
    
    save = raw_input('Do you sure to commit the above modifications? Y/N\n') 
    if not save[0] == 'Y':
    	sys.exit()

    f = open(fpath, 'w')
    try:
        f.write(''.join(buffer))
    finally:
        f.close()

对修改确认功能的单元测试
import unittest
from CommitModify import *

class Test(unittest.TestCase):    
    def testReplaceModify(self):
        self.assertEqual('Modify Sample: Modification',  
        replace_modify('Modify Sample: \modify {Origin text} {Modification}'))
        self.assertEqual('Modify Sample: {}{}',  
        replace_modify('Modify Sample: \modify {{}} {{}{}}'))
        self.assertEqual('t2 t4',  
        replace_modify('\modify {t1} {t2} \modify {t3} {t4}')) 
        self.assertEqual('Modify Sample: Modification',  
        replace_modify('Modify Sample: \modify{Origin text}{Modification}'))
                       
    def testReplaceDelete(self):
        self.assertEqual('Delete Sample: \\',  
        replace_delete('Delete Sample: \delete{Delete}\\'))
        self.assertEqual('Delete Sample: \\',  
        replace_delete('Delete Sample: \delete    {Delete}\\'))
        self.assertEqual('Delete Sample: \\',  
        replace_delete('Delete Sample: \delete{{{{{}}}}{}}\\'))
        self.assertEqual('',  
        replace_delete('\delete{Delete}\delete    {Delete}\delete{{{{{}}}}{}}'))
    
    def testReplaceInsert(self):
        self.assertEqual('Insert Sample: Insert\\',  
        replace_insert('Insert Sample: \\addtext{Insert}\\'))
        self.assertEqual('Insert Sample: Insert\\',  
        replace_insert('Insert Sample: \\addtext    {Insert}\\'))
        self.assertEqual('Insert Sample: {{{{}}}}{}\\',  
        replace_insert('Insert Sample: \\addtext{{{{{}}}}{}}\\'))
        self.assertEqual('InsertInsert{{{{}}}}{}',  
        replace_insert('\\addtext{Insert}\\addtext    {Insert}\\addtext{{{{{}}}}{}}'))

    def testNestedCommands(self):
        case0 = '\modify{\\addtext{\delete{hhee}pp}}{\modify{hehe}{ppp}}'
        self.assertEqual('ppp', 
            replace_modify(replace_delete(replace_insert(case0))))

if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()


你可能感兴趣的:(Latex,python)