yuureinohebi / gsut.py

#/usr/bin/env python3
"""Ghostscript utilities toolkit, like GLut, but better!"""
import sys
from functools import partial
import libgs
import gsu

class GhostScriptInterpreter(object):
    """A high level interface for Ghostscript. To push words, you only have
    to call methods on the object"""
    def __init__(self):
        gs = libgs.gsapi_new_instance()
        libgs.gsapi_init_with_args(gs, [
                    # doesn't matter that much, we use the default name
                    # quiet out copyright messages and stuff

        # create references to C functions, we have to keep these references
        # along, otherwise the GC might discard them and the callback fails
        self._stdout_handler_c = libgs.c_stdstream_t(self._stdout_handler)
        self._stderr_handler_c = libgs.c_stdstream_t(self._stderr_handler)
        self._stdin_handler_c = libgs.c_stdstream_t(self._stdin_handler)

        # set up stdio
        libgs.gsapi_set_stdio(gs, self._stdin_handler_c,
        # save for later use
        self._instance = gs
        self._stdout = ''
        self._stdout_expected = False

    def _stdout_handler(self, caller_handle, buf, length):
        """Handles the stdout of the Ghostscript interpreter"""
        value = str(buf, 'utf-8')
        if self._stdout_expected:
            self._stdout += value
            print(value, end='')
        # return length to signalize we handled the data
        return length

    def _stdin_handler(self, caller_handle, buf, length):
        # not yet known how to proceed with stdin
        print("stdin handler called", file=sys.stderr)
        return length

    _stderr_handler = _stdin_handler

    def number(self, value):
        """Pushes a number on the stack by converting into a string"""
        return self.raw(str(value))

    def string(self, value):
        return self.raw("({})".format(value))

    def raw(self, code):
        """Runs raw PostScript code on the current instance"""
        # prepend space to avoid clashing with stuff that might already
        # be on the stack
        gsu.run_code(self._instance, " {}".format(code))
        # always return self to make sure chainability works
        return self

    def __getattr__(self, name):
        """Returns a function that will push the value once called"""
        return partial(self.raw, code=name)

    def _parse_items(self, items):
        accumulator = list()
        for item in items:
            # a number?
            except ValueError:

            # a string?
            if item.startswith('(') and item.endswith(')'):

            # an array?
            if item.startswith('[') and item.endswith(']'):
                contents = item[1:-1]

            # yet unhandled type
            print('Unhandled type', item, file=sys.stderr)

        return accumulator

    def _pstack(self):
        """Returns the stack contents
        It also converts the primitive types int and string into
        Python types"""
        # now we expect stdout
        self._stdout_expected = True
        # pstack and flush to get the stack contents
        # we don't expect more stdout
        self._stdout_expected = False
        # feed the lines into the parser
        stack_contents = self._parse_items(self._stdout.splitlines())
        # reset stdout, for further runs
        self._stdout = ''
        return stack_contents

def main():
    gsi = GhostScriptInterpreter()
    # strange bug, seems to be a problem with ghostscript itself

if __name__ == '__main__':
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.