Bachmann1234 / java9_kernel

An ipython kernel for java 9
Apache License 2.0
72 stars 17 forks source link

Why does ipython notebook output shows everything? #16

Open shubhashis-k opened 8 years ago

shubhashis-k commented 8 years ago

I can't but notice that when each cell in ipython notebook produces output, it includes the whole code as well. capture

For example, look at the picture. It shows the method definition as well. clearly I don't need it as I've already wrote it. So, is there a way so that it would NOT show the method definition as well?

Also, the Jshell only shows Added method twice(String). So, can the output of ipython be manipulated? If so, how? (I don't know how to write ipython kernels)

Bachmann1234 commented 8 years ago

So there is no design reason the whole code shows again.

Though I'll admit I don't actually know too much about making ipython kernels either :-P. This was basically the result of an experiment where I took the WrapperKernel example and wrapped around the java 9 repel jar. Then @dsblank found the repo and added all sorts of fanciness to it.

You can take the output and separate useful output from useless output This is the function that returns the output to be displayed

If you (or whoever else) takes a shot at this you are going to have to be careful and make sure whatever method is used to separate redundant output from useful output generalizes nicely

Bachmann1234 commented 8 years ago

As for why this behavior is this way:

Basically I did the simplest thing that worked. I was mostly toying around with java9 and ipython.

shubhashis-k commented 8 years ago

Thanks for pointing to the function :).

dsblank commented 8 years ago

I've further refined the output to not print everything, but this can get complicated because kulla formats it (wraps). Here is some sample output:

https://athena.brynmawr.edu/jupyter/hub/dblank/public/CS206%20Data%20Structures/2016-Spring/Notebooks/LinkedListSummary.ipynb

Note also that the results are shown in the Out: area. It isn't correct yet... and the Java parser is really slow!

shubhashis-k commented 8 years ago

Yes, noticed the slow outputs. Also, does the code completion work? Pressing tab does not suggest anything for me.

Bachmann1234 commented 8 years ago

I doubt it. I think I would have to write something lower level then the wrapper kernel to do that. I could be wrong though.

Bachmann1234 commented 8 years ago

also @dsblank nice! Its super cool that this thing is being used to some capacity! I am sure when Java 9 is further along or out in the wild tools like this will get a lot better.

dsblank commented 8 years ago

Yes, when Java9 gets more stable, it will be nice.

BTW, I have hooked up basic command completions on class names, and variables.

Bachmann1234 commented 8 years ago

Heh, shows what I know :-P

shubhashis-k commented 8 years ago

@dsblank how did you manipulate the output? Also is there a documentation on manipulating the ipython outputs?

dsblank commented 8 years ago

I had to custom handle it... it is a bit of a hack right now. Basically, something like:

    def do_execute_direct(self, code, silent=False):
        """
        :param code:
            The code to be executed.
        :param silent:
            Whether to display output.
        :return:
            Return value, or None

        MetaKernel code handler.
        """
        if not code.strip():
            return None

        interrupted, output = self._execute_java(code)

        ## Process output to remove echos and trailing lines:

        original_output = output.split("\r\n")
        sources = code.split("\n")
        new_output = []
        output_pos = 0
        source_pos = 0
        for output_pos in range(len(original_output)):
            if source_pos == len(sources):
                new_output.append(original_output[output_pos])
            else:
                source_line = sources[source_pos]
                #print("cmp:", repr(source_line), repr(original_output[output_pos]))
                if ' ' + source_line == original_output[output_pos]:
                    # skip over it
                    source_pos += 1
                else:
                    new_output.append(original_output[output_pos])
        if len(new_output) >= 1 and new_output[-1].strip() == '':
            output = "\n".join(new_output[:-1])
        else:
            output = "\n".join(new_output)

        exitcode = "|  Error:" in output

        # Look for a return value:
        retval = None
        for expr in [".*\|  Expression value is: ([^\n]*)", 
                     ".*\|  Variable [^\n]* of type [^\n]* has value ([^\n]*)"]:
            match = re.match(expr, output, re.MULTILINE | re.DOTALL)
            if match:
                sretval = match.groups()[0]
                try:
                    # Turn string into a Python value:
                    retval = eval(sretval)
                except:
                    retval = sretval
                break

        if not silent:
            if exitcode:
                self.Error(output)
            else:
                print(output)
        return str(retval) if retval is not None else None

When the semester is over and I have some time, I'll make a real fix, and a PR.

dsblank commented 8 years ago

The completions:

    def get_completions(self, info):
        """
        Get command-line completions (TAB) from JShell:

        /vars
        |    Test test = Test@1c2c22f3

        /methods
        |    printf (Ljava/lang/String;[Ljava/lang/Object;)V
        |    draw ()V

        /classes
        |    class Test

        """
        token = info["help_obj"]
        matches = []
        for command, parts, part, text in [("/vars", 3, 1, ""),
                                           ("/methods", 2, 0, "()"),
                                           ("/classes", 2, 1, "()")]:
            interrupt, output = self._execute_java(command)
            for line in output.split("\n"):
                if len(line) > 1 and line[0] == "|":
                    items = line[1:].strip().split(" ", parts)
                    if items[part].startswith(token):
                        matches.append(items[part] + text)
        return matches
shubhashis-k commented 8 years ago

Thanks @dsblank :)