-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
617 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() |