/gkdtex

A programmable, TeX-compatible and 2-stage typesetting language.

Primary LanguagePythonMIT LicenseMIT

GKD TeX

TeX that σ`∀´)!

python setup.py install and you can have the gkdtex command.

The syntax is compatible to TeX. Before executing a TeX engine, a part of TeX commands understandable to gkdtex are preprocessed, generating TeX code.

The usage is:

gkdtex main.tex [--config_dir <str>] [--out_file <str>=main.out.tex].

In GKD-TeX, there are 3 kinds of commands.

The first is a Python function provided by a Python file(usually in your $config_dir/.gkdrc.py or other gkd packages), you can check examples at Python module gkdtex.builtins.*.

The other 2, CBV(Call By Value) Commands and 2. CBN(Call By Name) Commands, are similar, can be defined via \gkd@def or \gkd@def@lazy.

Commands without any arguments shall be a constant string.

Gkd Packages

Some Gkd packages providing productive tools can be installed via pip.

  • gkdbnf: painless BNF writing; no dependencies.
  • gkdhighlight: syntax highlighting for vast programming languages; extensible; no dependencies other than xcolor and amsmath.
  • gkdtikz.tree: simple TikZ trees with Yaml syntax.

P.S: For a package $a.$b.$c, use pip install $a.

Python Commands

A minimal gkd package can be written in $config_dir/mininalplugin.py:

from gkdtex.interpreter import Interpreter
from gkdtex.developer_utilities import *

def arginfo(*args: Group, tex_print, **kwargs):
    tex_print(
        "{} positional arguments, keyword arguments: {{ {} }}".format(
            len(args),
            ','.join(kwargs.keys())
        )
    )

class GkdInterface:
    @staticmethod
    def load(self: Interpreter, text_print):
        if 'narg' in self.globals:
            raise NameError("'narg' has already been defined.")
        self.globals['arginfo'] = arginfo
\gkd@usepackage{mininalplugin}
\arginfo{1}{2}{3}{^a 1} % '3 positional arguments, keyword arguments: { a,self }'

\gkd@verb(requires fancyvrb)

\gkd@verb{ {1, 2, 3}  a} % \verb& {1, 2, 3}  a&

\gkd@usepackage

A GKD package is made from a Python module. \gkd@usepackage{module_name} will do import("module_name").

The module search path is Python sys.path, with $config_dir appended.

In that module you should provide a namespace GkdInterface, GkdInterface should have 1 or 2 elements, GkdInterface.load and GkdInterface.dispose(optional).

Check runtest/plugin_A.py for how to implement load or dispose.

\gkd@input

\gkd@input{some_file} literally inputs source code in some_file.

Note that some_file is the relative path. The base is the directory of the proceeding document.

CBV Commands

\gkd@def defines your own Call By Value command. You can define a Call By Name command by using \gkd@def@lazy.

  • Positional arguments

     \gkd@def{\a{}}{#\1 + #\1}
     \a{1} % '1 + 1'
  • Keyword arguments

    \gkd@def{\a{^a}{^b}}{#\a^#\b}
    \a{^b x}{^a y} % 'y + x' 
  • Optional arguments

    \gkd@def{\a{1}{^b k_a}}{ #\1 + #\b }
    \a % '1 + k_a'

\gkd@pyexec and \gkd@pyeval

\gkd@pyeval{1 + 1} % 2
\gkd@def{\add{}{}}{#\1 + #\2}

\gkd@pyexec{
    x = r"\add{1}"
}

\gkd@pyeval{^expand after=True}{x + "{1}"} % 1 + 1

P.S: You can use Python variable tex_print(string) to put string in the generated tex file, and you can use self to access the interpreter in case you need to inspect information such as frames(self.frames), current filename(self.filename), current source code(self.src), etc.