from __future__ import print_function from metakernel import MetaKernel import sys import signal import yap import yapex import ipywidgets as widgets def eprint(*args, **kwargs): print(*args, file=sys.stderr, **kwargs) class MetaKernelyap(MetaKernel): implementation = 'MetaKernel YAP' implementation_version = '1.0' language = 'text' language_version = '0.1' banner = "MetaKernel YAP" language_info = { 'mimetype': 'text/prolog', 'name': 'text', # ------ If different from 'language': 'codemirror_mode': { "version": 2, "name": "prolog" }, 'pygments_lexer': 'prolog', 'version' : "0.0.1", 'file_extension': '.yap', 'help_links': MetaKernel.help_links, } def __init__(self, **kwargs): MetaKernel.__init__(self, **kwargs) self._start_yap(**kwargs) self.olines = "" self.ask = True def _start_yap(self, **kwargs): # Signal handlers are inherited by forked processes, and we can't easily # reset it from the subprocess. Since kernelapp ignores SIGINT except in # message handlers, we need to temporarily reset the SIGINT handler here # so that yap and its children are interruptible. sig = signal.signal(signal.SIGINT, signal.SIG_DFL) try: self.engine = yap.YAPEngine() self.q = None self.engine.query("load_files(library(python), [])").command() self.engine.query("load_files(library(jupyter), [])").command() banner = "YAP {0} Kernel".format(self.engine.version()) self.olines = banner finally: signal.signal(signal.SIGINT, sig) # Register Yap function to write image data to temporary file #self.yapwrapper.run_command(image_setup_cmd) def get_usage(self): return "This is the YAP kernel." def query_prolog(self, s): if not self.q: self.q = self.engine.query(s) if self.q.next(): myvs = self.q.namedVarsCopy() wrote = False if myvs: i = 0 for peq in myvs: name = peq[0] bind = peq[1] if bind.isVar(): var = yap.YAPAtom('$VAR') f = yap.YAPFunctor(var, 1) bind.unify(yap.YAPApplTerm(f, (name))) else: i = bind.numberVars(i, True) print(name.text() + " = " + bind.text()) wrote = True print("yes") if self.q.deterministic(): self.closeq() return print("No (more) answers") self.closeq() return def closeq( self): if self.q: self.q.close() self.q = None def do_execute_direct(self, code): if not code.strip(): return "" lines = code.split("\n") interrupted = False self.doReset = True nlines = "" try: for line in lines: line = line.strip() if line.startswith('#'): # wait print( "comment") elif line.startswith('%'): # wait call_magic( line ) elif line.endswith(';'): nlines += line.rstrip(';').rstrip() self.doReset = False break elif line.endswith('!'): nlines += line.rstrip('!').rstrip() self.ask = False self.doReset = False break else: line = line.rstrip() if line: nlines += line + "\n" if nlines != self.olines: self.closeq( ) self.olines = nlines elif self.doReset: opt = widgets.ToggleButtons( description='Query Solutions:', options=['First', 'Next', 'All'], ) print( opt ) if opt == 'First': self.closeq( ) elif opt == 'Next': self.doReset = False else: self.ask = False self.doReset = False self.query_prolog( nlines ) while not self.ask and self.q: self.query_prolog( nlines ) except SyntaxError as err: print("Syntax Error error: {0}".format(err)) except EOFError: return except RuntimeError as err: print("YAP Execution Error: {0}".format(err)) except ValueError: print("Could not convert data to an integer.") except KeyboardInterrupt: return 'stopped by user' except: print("Unexpected error:", sys.exc_info()[0]) raise def do_complete(self, code, cursor_pos): print(code) print(cursor_pos) eprint( code, " -- ", str(cursor_pos ) ) # code = code[:cursor_pos] # default = {'matches': [], 'cursor_start': 0, # 'cursor_end': cursor_pos, 'metadata': dict(), # 'status': 'ok'} # if not code or code[-1] == ' ': # return default # tokens = code.replace(';', ' ').split() # if not tokens: # return default # matches = [] # token = tokens[-1] # start = cursor_pos - len(token) # if token[0] == '$': # # complete variables # cmd = 'compgen -A arrayvar -A export \ # -A variable %s' % token[1:] # strip leading $ # output = self.bashwrapper.run_command(cmd).rstrip() # completions = set(output.split()) # # append matches including leading $ # matches.extend(['$'+c for c in completions]) # else: # # complete functions and builtins # cmd = 'compgen -cdfa %s' % token # output = self.bashwrapper.run_command(cmd).rstrip() # matches.extend(output.split()) # if not matches: # return default # matches = [m for m in matches if m.startswith(token)] # return {'matches': sorted(matches), 'cursor_start': start, # 'cursor_end': cursor_pos, 'metadata': dict(), # 'status': 'ok'} def repr(self, data): return repr(data) if __name__ == '__main__': try: from ipykernel.kernelapp import IPKernelApp except ImportError: from jupyter_client.zmq.kernelapp import IPKernelApp IPKernelApp.launch_instance(kernel_class=MetaKernelyap)