Search code examples
python-3.xlatexsublimetextsublime-text-plugin

Sublime and Python: How to use Python Plugin to create neat equations from Scientific Workplace in Latex


I am using a program that helps in writing latex. However, there is a problem that everytime I write an argument it display it as eqnarray*

For example

\begin{eqnarray*}
r_{t}^{p} &=&\frac{P_{t}-P_{t-1}}{P_{t-1}} \\
&=&\frac{\left( \left( 1-\alpha \right) r_{t}^{\ast }-\alpha \right)
P_{t-1}+\alpha A_{t}}{P_{t-1}} \\
&=&\left( 1-\alpha \right) r_{t}^{\ast }-\alpha +\alpha \frac{A_{t}}{P_{t-1}}
\\
&=&\left( 1-\alpha \right) r_{t}^{\ast }+\alpha \left( \frac{A_{t}}{P_{t-1}}%
-1\right) 
\end{eqnarray*}

I want it to look more organized as so

\begin{equation*}
    \begin{split} 
        r_{t}^{p} &=\frac{P_{t}-P_{t-1}}{P_{t-1}} \\ 
        &=\frac{((1-\alpha) r_{t}^{\ast}-\alpha) P_{t-1}+\alpha A_{t}}{P_{t-1}} \\ 
        &=(1-\alpha) r_{t}^{\ast}-\alpha +\alpha \frac{A_{t}}{P_{t-1}} \\ 
        &=(1-\alpha) r_{t}^{\ast}+\alpha (\frac{A_{t}}{P_{t-1}} -1) 
    \end{split}
\end{equation*}

I am using Sublime text 3 editor, therefore, I find myself doing the same thing again and again which is the following steps

  1. replace all the \ with /
  2. make it one line

    s= '/begin{eqnarray*} r_{t}^{p} &=&/frac{P_{t}-P_{t-1}}{P_{t-1}} // &=&/frac{/left( /left( 1-/alpha /right) r_{t}^{/ast }-/alpha /right) P_{t-1}+/alpha A_{t}}{P_{t-1}} // &=&/left( 1-/alpha /right) r_{t}^{/ast }-/alpha +/alpha /frac{A_{t}}{P_{t-1}} // &=&/left( 1-/alpha /right) r_{t}^{/ast }+/alpha /left( /frac{A_{t}}{P_{t-1}}% -1/right) /end{eqnarray*}'

  3. remove %

    s=s.replace("%", "") s

  4. replace eqnarray* by equation*

    s1=s.replace("eqnarray*", "equation*")

  5. if the text include // then include a \begin{split} directly after \begin{equation*} and \end{split} before \end{equation}

    if '//' in s1: f1 = "equation*}" f2='/end{equation*}' s3=s1[:s1.index(f1) + len(f1)] + '/begin{split}' + s1[s1.index(f1) + len(f1):] s4= s3[:s3.index(f2)] + '/end{split}' + s3[s3.index(f2):s3.index(f2) + len(f2)]

etc...

I have written a plugin code as so

import sublime, sublime_plugin, re, string   #import the required modules

class RonvertCommand(sublime_plugin.TextCommand): #create Text Command
    def run(self, edit):   #implement run method
        for region in self.view.sel():  #get user selection
            if not region.empty():  #if selection not empty then
                s = self.view.substr(region)  #assign s variable the selected region
                s4=s.replace("%", "")
                # s1=s.replace("eqnarray*", "equation*")
                if '\\begin{eqnarray*}' in s4:
                    s4=s4.replace("eqnarray*", "equation*")
                    f1 = "equation*}"
                    s4=s4[:s4.index(f1) + len(f1)] + '\\begin{split}' + s4[s4.index(f1) + len(f1):]
                    f2='\\end{equation*}'
                    s4= s4[:s4.index(f2)] + '\end{split}' + s4[s4.index(f2):s4.index(f2) + len(f2)]
                if '\\end{eqnarray*}' in s4:
                    s4=s4.replace("eqnarray*", "equation*")
                    f2='\\end{equation*}'
                    s4= s4[:s4.index(f2)] + '\end{split}' + s4[s4.index(f2):s4.index(f2) + len(f2)]
                s4=s4.replace("&=&", "&=")
                s4=s4.replace("\\left", "")
                s4=s4.replace("\\right", "")
                s4=s4.replace("( ", "(")
                s4=s4.replace(" )", ")")
                s4=s4.replace(" }", "}")
                s4=s4.replace(" _{", "_{")
                s4=s4.replace("[ ", "[")
                s4=s4.replace(" ]", "]")
                s4=s4.replace("& =", "&=")
                s4=s4.replace("+(", "+ (")
                # s1 = '\n'.join([' '.join(para.splitlines()) for para in s.split('\n\n')])
                self.view.replace(edit, region, s4) #replace content in view

However, I still need to do some steps before I use the plugin and after I use it. This is because I can not simply write \ in python I need to write it as / can anybody help me reach this desirable thing without these mess?

Thank you


Solution

  • I have solved my problem with noticing some nice issues. First realized that before coding it into sublime text 3 plug-in we have to do some tests on python Jupyter notebook. As I mentioned in my question the problem with taking strings in \ is a problematic therefore in sublime text 3 it automaticall transform it to \\ therefore, to do some testing on python it is always better to replace all \ with a \\ and then paste it as a string in python. This what I have done and I was able to fix my problem.

    The code goes as follow

    import sublime, sublime_plugin, re, string   #import the required modules
    
    class RonvertCommand(sublime_plugin.TextCommand): #create Text Command
        def run(self, edit):   #implement run method
            for region in self.view.sel():  #get user selection
                if not region.empty():  #if selection not empty then
                    s = self.view.substr(region)  #assign s variable the selected region
                    s4=s.replace("%", "")
                    if '\\begin{eqnarray*}' in s4:
                        s4=s4.replace("eqnarray*", "equation*")
                        f1 = "equation*}"
                        s4=s4[:s4.index(f1) + len(f1)] + '\n\t\\begin{split}' + s4[s4.index(f1) + len(f1):]
                        f2='\\end{equation*}'
                        s4= s4[:s4.index(f2)] + '\t\\end{split}\n' + s4[s4.index(f2):s4.index(f2) + len(f2)]
                        ss=s4.split('\n')
                        while '\\\\' in ss:
                                a=ss.index('\\\\')
                                ss[a-1]= ss[a-1] + '\\\\'
                                del ss[a]
                        a=ss.index('\t\\end{split}')
                        ss[a-1]=ss[a-1]+ '\\\\'
                        for x in range(ss.index('\t\\begin{split}')+1,ss.index('\t\\end{split}')-1):
                            if x<ss.index('\t\\end{split}')-1:
                                if '&=&' and '\\\\' not in ss[x]:
                                    ss[x]=ss[x]+ss[x+1]
                                    del ss[x+1]
                        for x in range(ss.index('\t\\begin{split}')+1,ss.index('\t\\end{split}')):
                            ss[x]='\t\t'+ ss[x]
                        s4="\n".join(ss)  
    
                    elif ('\\[' in s4) or ('\\begin{equation*}' in s4):
                        s4=s4.replace("\\[","\\begin{equation*}")
                        s4=s4.replace("\\]","\\end{equation*}")
                        ss=s4.split('\n')
                        for x in range(2,len(ss)-1):
                            ss[1]=ss[1]+ss[x]
                        ss=[ss[0],ss[1], ss[-1]]
                        s4="\n".join(ss)
                        s4=s4[0:s4.index('\n')+1]+'\t'+s4[1+s4.index('\n')::]
                    # For all the sentences beteween I want to insert two tabs 
                    s4=s4.replace("&=&", "&=")
                    s4=s4.replace("&&", "&")
                    s4=s4.replace("\\left", "")
                    s4=s4.replace("\\right", "")
                    s4=s4.replace("( ", "(")
                    s4=s4.replace(" )", ")")
                    s4=s4.replace(" }", "}")
                    s4=s4.replace(" _{", "_{")
                    s4=s4.replace("[ ", "[")
                    s4=s4.replace(" ]", "]")
                    s4=s4.replace("& =", "&=")
                    s4=s4.replace("+(", "+ (")
                    s4=s4.replace("+\\", "+ \\")
                    s4=s4.replace("}+", "} +")
                    s4=s4.replace(") -(", ")-(")
                    s4=s4.replace(") -(", ")-(")
                    s4=s4.replace(") (", ")(")
                    s4=s4.replace(") -", ")-")
                    s4=s4.replace(") ^", ")^")
                    s4=s4.replace(") $", ")$")
                    s4=s4.replace("} +", "}+")
                    s4=s4.replace("\\text{ and}", "\\qquad\\text{and}\\qquad ")
                    s4=s4.replace("\\text{ or}", "\\qquad\\text{or}\\qquad ")
                    s4=s4.replace("\\text{ where}", "\\text{,}\\qquad\\text{where}\\qquad")
    
                    if '\\vert' in s4:
                        Vert = re.findall('vert', s4)
                        for i in range(0,int(len(Vert)/2)):
                            A=re.search(r'(\\vert.*?\\vert)', s4).group(1)
                            s3=re.sub(r"{array}{([a-z])\1+}", "{vmatrix}", A)
                            s3=re.sub(r"{array}", "{vmatrix}", s3)
                            s3=s3.replace("\\vert", "")
                            s4=s4[0:s4.index(A)]+s3+s4[s4.index(A)+len(A):]
                    s4=s4.replace("\\text{if}", "\\text{if}\\qquad ")
    
                    if '(' in s4:
                        start = '('
                        end = ')'
                        A=s4[s4.find(start)+len(start):s4.rfind(end)-1]
                        if '(' in A:
                            s4=s4[:s4.find(start)]+'\\Big('+s4[s4.find(start)+len(start):s4.rfind(end)]+'\\Big)'+s4[1+s4.rfind(end)::]
    
    
                    self.view.replace(edit, region, s4) 
    
                    #replace content in view
                    # self.view.replace(edit, region, s.count('\n')) #replace content in view
                    # self.view.insert(edit, 0, s.count('\n'))
    

    Additional steps for Keybindings

    1- go to Keybinding (Preference-Key bindings)

    2- paste the following:

    {"keys": ["alt+x"], "command": "ronvert"},
    

    3- save it and close

    now you can select all the text and just apply press alt x on windows enter image description here