Skip to content

Commit

Permalink
Copy of base version
Browse files Browse the repository at this point in the history
  • Loading branch information
YuvaAthur committed Apr 5, 2016
1 parent 2e9875c commit aa2b96c
Show file tree
Hide file tree
Showing 5 changed files with 617 additions and 0 deletions.
115 changes: 115 additions & 0 deletions jkernel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from __future__ import print_function

from ipykernel.kernelbase import Kernel

import base64
import os

from wrapper import JWrapper

# CUSTOMIZE HERE
# Viewmat creates a temporary picture file in order to display it.
# This is the path the kernel will use to find it.
j_viewmat_image_location = "~/j64-804-user/temp/viewmat.png"

class JKernel(Kernel):
implementation = 'jkernel'
implementation_version = '0.1'
language_info = {
'mimetype': 'text/plain',
'name': 'J',
'file_extension': 'ijs'
}
banner = "J language kernel"
help_links = [
{'text': 'Vocabulary', 'url': 'http://www.jsoftware.com/help/dictionary/vocabul.htm'},
{'text': 'NuVoc', 'url': 'http://www.jsoftware.com/jwiki/NuVoc'}
]

def __init__(self, *args, **kwargs):
super(JKernel, self).__init__(*args, **kwargs)
self.j = JWrapper()

assert self.j.sendline("2+2") == "4\n" # make sure everything's working fine

def do_execute(self, code, silent, store_history=True, user_expressions=None, allow_stdin=False):

lines = code.splitlines()

generates_image = True if lines[-1].startswith("viewmat ") or lines[-1].startswith("viewrgb ") else False

output = self.j.sendlines(lines)

if not silent:

def handle_text_response():
if not output:
return
stream_content = {'name': 'stdout', 'text': output}
self.send_response(self.iopub_socket, 'stream', stream_content)

def handle_image_response():
image_path = os.path.expanduser(j_viewmat_image_location)
with open(image_path, "rb") as file:
file = base64.b64encode(file.read()).decode()
os.remove(image_path)

stream_content = {
'source': 'meh',
'data': {'image/png': file},
'metadata': {'image/png': {'width': 300, 'height': 300}}
}
self.send_response(self.iopub_socket, 'display_data', stream_content)

if not generates_image:
handle_text_response()
else:
try:
handle_image_response()
except:
handle_text_response()

return {'status': 'ok',
# The base class increments the execution count
'execution_count': self.execution_count,
'payload': [],
'user_expressions': {},
}

def do_shutdown(self, restart):
self.j.close()

def do_inspect(self, code, cursor_pos, detail_level=0):

inspection = ""

code += "\n"
line = code[code.rfind("\n", 0, cursor_pos)+1 : code.find("\n", cursor_pos)]

line_pos = cursor_pos - code.rfind("\n", 0, cursor_pos) - 2

found = False

if line[line_pos].isalnum():
i, j = line_pos, line_pos
while i > 0 and line[i-1].isalnum() or line[i-1] == "_":
i -= 1
while j < len(line)-1 and line[j+1].isalnum() or line[j+1] == "_":
j += 1
if line[i].isalpha():
if j == len(line)-1 or line[j+1] not in ".:":
name = line[i:j+1]
inspection = self.j.sendline(name)
found = True

return {
'status': 'ok',
'data': {'text/plain': inspection},
'metadata': {},
'found': found
}


if __name__ == '__main__':
from ipykernel.kernelapp import IPKernelApp
IPKernelApp.launch_instance(kernel_class=JKernel)
5 changes: 5 additions & 0 deletions kernel.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"argv": ["python","-m","jkernel", "-f", "{connection_file}"],
"display_name": "j-kernel",
"language": "j"
}
9 changes: 9 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
![](http://i.imgur.com/wL5ZTfu.png)

To install: place the files in ~/.ipython/kernels/jkernel* directory. Make sure that the paths to J at the top of wrapper.py and jkernel.py are correct. For those unfamiliar with Python, the file path on Windows needs backslashes escaped; for example: `"C:\\Program Files\\j64-804\\bin"`. Open `jupyter notebook` (or `ipython notebook`, but it's deprecated) from this directory.

(* or the newer location: `~/.local/share/jupyter/kernels/jkernel` on Linux, `%APPDATA%\jupyter\kernels\jkernel` on Windows, `~/Library/Jupyter/kernels/jkernel` on OSX.)

Requires IPython 3.0+, possibly 4.0+.

(in theory jkernel.py should be placed in Python's `dist-packages` directory to be accessible from everywhere, but that's not important at this stage)
392 changes: 392 additions & 0 deletions sample_edge_detect.ipynb

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions wrapper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
from __future__ import print_function

from ctypes import *

import sys
import os

# CUSTOMIZE HERE
# J binary directory (the one with all the binaries)
j_bin_path = os.path.expanduser("~/j64-804/bin")

def get_libj(binpath):
if os.name == "nt":
lib_path = binpath + "/j.dll" # Windows
elif sys.platform == "darwin":
lib_path = binpath + "/libj.dylib" # OSX
else:
lib_path = binpath + "/libj.so" # Linux
libj = cdll.LoadLibrary(lib_path)

libj.JInit.restype = c_void_p
libj.JSM.argtypes = [c_void_p, c_void_p]
libj.JDo.argtypes = [c_void_p, c_char_p]
libj.JDo.restype = c_int
libj.JFree.restype = c_int
libj.JFree.argtypes = [c_void_p]

return libj

class JWrapper:
def __init__(self):

binpath = j_bin_path

self.libj = get_libj(binpath)
self.j = self.libj.JInit()

# buffer for multiline input,
# for normal line input and J explicit definitions.
self.input_buffer = []

OUTPUT_CALLBACK = CFUNCTYPE(None, c_void_p, c_int, c_char_p)
INPUT_CALLBACK = CFUNCTYPE(c_char_p, c_void_p, c_char_p)

def output_callback(j, output_type, result):
output_types = [None, "output", "error", "output log", "assert", "EXIT", "1!:2[2 (wat)"]
self.output_type = output_types[output_type]
self.output = result.decode('utf-8', 'replace')

def input_callback(j, prompt):
if not self.input_buffer:
return b")"
line = self.input_buffer.pop(0)
return line.encode()

callbacks_t = c_void_p*5
callbacks = callbacks_t(
cast(OUTPUT_CALLBACK(output_callback), c_void_p),
0,
cast(INPUT_CALLBACK(input_callback), c_void_p),
0,
c_void_p(3) # defines "console" frontend (for some reason, see jconsole.c, line 128)
)
self.libj.JSM(self.j, callbacks)

self.sendline("ARGV_z_=:''")
self.sendline("BINPATH_z_=:'{}'".format(binpath))
self.sendline("1!:44'{}'".format(binpath))
self.sendline("0!:0 <'profile.ijs'")
self.sendline("(9!:7) 16 17 18 19 20 21 22 23 24 25 26 { a.") # pretty boxes

def close(self):
self.libj.JFree(self.j)

def sendline(self, line):
self.output = None
self.libj.JDo(self.j, c_char_p(line.encode()))
if not self.output:
return ""
return self.output

def sendlines(self, lines):
self.input_buffer = lines
output = ""
while self.input_buffer:
line = self.input_buffer.pop(0)
output += self.sendline(line)
return output

if __name__ == "__main__":
j = JWrapper()
j.sendline("load 'viewmat'")
j.sendline("load 'bmp'")
j.sendline("VISIBLE_jviewmat_ =: 0")
#j.sendline("viewmat i. 5 5")
j.close()

0 comments on commit aa2b96c

Please sign in to comment.