文字列が有効な LaTex ルールであるかどうかを確認するにはどうすればよいでしょうか?

文字列が有効な LaTex ルールであるかどうかを確認するにはどうすればよいでしょうか?

私はMathQuillライブラリを使用しています数式入力操作の数を制限しようとしています。何か方法はありますでしょうか?文字列と LaTex ルールを区別するには?

例えば:

def check('\sum') => True  #LaTex rule
def check('\myCustomVar') => False  #NOT a LaTex rule

どのような助けでも大歓迎です!

答え1

少なくとも Linux では (Windows についてはわかりません)、latexdefコマンドラインから LaTeX 定義を検索する Martin Scharrer によるスクリプトがあります。

latexdef section 

印刷されます

\section
\long macro:->\@startsection {section}{1}{\z@ }{-3.5ex \@plus -1ex \@minus -.2ex}{2.3ex \@plus .2ex}{\normalfont \Large \bfseries }

一方

latexdef sausage 

印刷されます

\sausage
undefined

latexdefPython からは次のように呼び出すことができます:

import subprocess, re

def latexdef(command_list, *args):
    '''
    call latexdef on a list of commands to be looked up
    *args can be used to pass options to latexdef
    '''
    p = subprocess.Popen(['latexdef'] + list(args) + command_list, \
                        stdout=subprocess.PIPE, \
                        stderr=subprocess.STDOUT)
    return p.communicate()[0].strip()

def are_commands(command_list, *args):
    '''
    look up multiple commands and return results in a dict
    '''
    result = latexdef(command_list, *args)
    frags = [ f.splitlines() for f in re.split(r'\n{2,}', result, re.MULTILINE) ]
    return { command[1:] : defn != 'undefined' for command, defn in frags }

def is_command(command, *args):
    '''
    look up a single command
    '''
    return are_commands([command],*args).values()[0]

if __name__ == '__main__':
    commands = "chapter section sausage".split()

    for command in commands:
        print command, is_command(command)

    print "\nwith book class loaded"

    for command in commands:
        print command, is_command(command, '-c', 'book')

    print "\nall at once, with class book"
    print are_commands(commands, '-c', 'book')

これは印刷されます

chapter False
section True
sausage False

with book class loaded
chapter True
section True
sausage False

all at once, with class book
{'sausage:': False, 'section:': True, 'chapter:': True}

の各呼び出しはlatexdefかなり遅いですが、1 回の呼び出しで複数のコマンドを検索することで時間を節約できます。これが の目的でありare_commands、辞書内の各コマンドの検索結果を返します。

また、これはlatexdefPerl スクリプトなので、これがあなたにとってどれほど重要かに応じて、全体を Python に翻訳して仲介者を省くのが合理的かもしれません。しかし、これはかなり長いスクリプトであり、Perl は目に負担がかかりすぎます...

答え2

これは実際の回答ではなく、より長いコメントです。Michael Palmer による回答は、それらのマクロがコア パッケージ/クラスによって定義されている場合、ほとんどの場合に機能します。

ただし、考慮する必要があるケースがいくつかあります。LaTeX の規則では、その作成方法はコマンド シーケンスを意味する可能性があります。一般的な LaTeX コマンド シーケンス (次の例では「cmd」と呼びます) は、次の ABNF として生成できます。

cmd = "\" 1*ALPHA

しかし、それだけでは十分ではありません。内部マクロを個別に含めたり除外したりする必要があることに注意してください。つまり、次のようなものをチェックする必要があるということです。

cmd = "\" 1*(ALPHA | "@")

内部マクロ用。このようなコマンド シーケンスが使用される時点で有効かどうかは、コンテキストに依存します。このルールはコマンド自体の有効性をチェックしますが、\makeatletter ... \makeatother有効であるためにはほとんどの場合、環境内で使用する必要があります (チェックにコンテキストを含める必要がある場合)。

また、チェックにコンテキストを含める必要があることは、 のようなコマンドで簡単に示せます\frac。これは、数式モードで使用する場合にのみ「有効な LaTeX ルール」です。または、 のようなコマンド\meterでのみ有効ですsiunitx

\ExplSyntaxOnもう 1 つのケースは expl3 です。l3 コマンドは、とで囲まれている場合、LaTeX でも有効です\ExplSyntaxOff。次のような形式で構築されます。

cmd = "\" 1*(ALPHA | "_") ":" 0*ALPHA

コロンの後の文字は制限されているため、これは実際には完全に正しくありませんが、十分なはずです。

\csname ...\endcsnameまた、ユーザーにはさらに多くのオプションがあるため、ユーザー定義マクロの有効性をチェックしたい場合は、状況はさらに悪化します。

アップデート:結局のところ、最も興味深い部分は、呼び出しが有効かどうかもチェックすることです。つまり、関数のシグネチャもチェックしてから、コマンドの呼び出しをチェックする必要があります。つまり、\fracは数式モード内から呼び出され、2 つの必須引数がある場合にのみ有効になります。 Fi のようになります$\frac{1}{2}$。実際のパーサーはここで非常に複雑になるため、おそらくサンプル ドキュメントをコンパイルする必要があるポイントです。

これらの方法には、1 つの注意点があります。LaTeX コマンド シーケンスだけでなく、TeX コマンド シーケンスも取得されます。特に LaTeX コマンド シーケンスを取得しようとして、TeX コマンド シーケンスを除外しようとすると、問題が発生します。

アップデート2:テストの実装に興味があったので、一致に使用できる正規表現をいくつか示します。完全に一致する場合にのみ、実際に有効なシーケンスが目の前に表示されます。コンテキスト依存の部分では、先読みと後読みを使用することをお勧めします。

  • 標準 LaTeX:\\[A-Za-z]*
  • 内部LaTeX:\\[A-Za-z@]*
  • expl構文:\\[A-za-z@_]*:[DNncVvoOxfTFpw]*
  • \csnameコマンド: 次のようなもの\\.*$

関連情報