Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added copy to clipboard button to external output area #954

Merged
merged 6 commits into from
Sep 9, 2017
Merged

Added copy to clipboard button to external output area #954

merged 6 commits into from
Sep 9, 2017

Conversation

callmeish
Copy link
Contributor

Addressed the feature request in #845. Testing using python scripts gives identical functionality to hydrogen without these changes, the only difference being the added copy to clipboard button.
2017-08-24-16 40 41

Copy link
Member

@BenRussert BenRussert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the pr! 🎉

Nice job figuring this out overall! There are a couple things to fix, should be no big deal.

Welcome and let me know if you have questions!

<div
className="btn icon icon-clippy"
onClick={ function() {
atom.clipboard.write(kernel.outputStore.outputs[kernel.outputStore.index].text.trim());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main reason tests are not passing is because flow wants you to handle cases where kernel or kernel.outputStore are undefined.

It should be fine if you do something like:

if (!kernel || !kernel.outputStore) return;

just above this line.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stream outputs, e.g. from print(), have an output.text property. Other execution results have no text property so we will need to look for output.data mime bundles, with 'text/plain' being the lowest/plainest common denominator.

// add up top: 
import { toJS } from "mobx"; 
import _ from "lodash"; 
// ...

const handleClick = () => {
    if (!kernel || !kernel.outputStore) return;
    // output should be converted to a plain js object first:
    const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]);

    // check for a text property and fall back to data["text/plain"]
    // there are other ways of doing this if you like, but for example:
    const textOrBundle = _.has(output, "text")
      ? output.text
      : output.data["text/plain"];

    atom.clipboard.write(textOrBundle);
    atom.notifications.addSuccess("Copied to clipboard");
  };

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't realize that the output might not be something with an output.text property, thanks for catching that. The style thing was a good idea as well.

I do have a question as far as the case where kernel or kernel.outputStore are undefined. That entire function is (or was, as I moved it out of an anonymous function) nested inside a div that wouldn't even appear if kernel.outputStore.outputs.length returned a value less than or equal to 0. Would that condition not require that both kernel and kernel.outputStore be defined?

flex: "0 0 auto",
width: "fit-content"
}}
>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor thing 😄

Since we are using the same style, why not put this into a variable right below EmptyMessage up top:

const buttonStyle = {
  flex: "0 0 auto",
  width: "fit-content"
};

// then in the component:
style={buttonStyle}

@@ -17,8 +19,24 @@ const EmptyMessage = () => {
);
};

const handleClick = () => {
//convert output to a plain js object
const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

kernel isn't defined here so this fails tests. It should come from the store like below.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

☝️ you can check if you caught the flow errors locally by running npm run flow from the root of your hydrogen project directory.

@rgbkrk I was thinking you could just move handleClick into the outputArea observer function, then add:

  const handleClick = () => {
    if (!kernel || !kernel.outputStore) return;

to satisfy flow?

@rgbkrk
Copy link
Member

rgbkrk commented Aug 31, 2017

I just merged in a PR that changed formatting, you'll need to rebase (and likely make sure to upgrade dependencies).

@BenRussert
Copy link
Member

@callmeish want to join our slack channel? This is close, but the minor details like flow and the conflicts from our prettier upgrade could be confusing 😆

@callmeish
Copy link
Contributor Author

Rebased, tested, should be good now. Thanks a bunch for the tip on local flow testing.

@lgeiger
Copy link
Member

lgeiger commented Sep 7, 2017

@callmeish Thanks a lot for the work and the rebase!
Unfortunately after the rebase this includes a lot of commits that are already present on master (take a look at the changed files) so we are unable to merge this.

To fix this a interactive rebase is necessary:

git remote update
git checkout copy-external-output 
git rebase -i upstream/master

Remove the commits unrelated to this PR in the editor that will pop up and you should be good to go.

If you need help with this feel free to join our slack channel.

Copy link
Member

@lgeiger lgeiger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@callmeish Since we're waiting with #978 for this to be merge, I rebase this PR and appended a minor fix for the case where no text/plain mime type is available (e.g. plotly plot).

This should now be good to merge.

Thanks again for digging into this. I invited you to the nteract organisation 🎉 .
We're very happy if you'd like to help us maintaining Hydrogen.

const handleClick = () => {
if (!kernel || !kernel.outputStore) return;
//convert output to a plain js object
const output = toJS(kernel.outputStore.outputs[kernel.outputStore.index]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if we really need to convert it but it doesn't hurt.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had some error without it (not consistently)

@lgeiger
Copy link
Member

lgeiger commented Sep 9, 2017

An alternative approach would be to get the text directly from the DOM as it is done in the result view component.
Though I kind of prefer the approach taken here because it consistently copies only the plain text representation. The only drawback is that we can't properly handle ANSI codes this way.
In a future PR we should come up with consistent way of handling this.

Copy link
Member

@BenRussert BenRussert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @callmeish, I hope you stick around!

@BenRussert BenRussert merged commit a6ff22c into nteract:master Sep 9, 2017
BenRussert pushed a commit that referenced this pull request Sep 9, 2017
BenRussert pushed a commit that referenced this pull request Sep 9, 2017
@BenRussert
Copy link
Member

An alternative approach would be to get the text directly from the DOM as it is done in the result view component.
Though I kind of prefer the approach taken here because it consistently copies only the plain text representation.

I like this approach as well, another benefit is it can be done without refs which the react docs say should be used sparingly.

@lgeiger
Copy link
Member

lgeiger commented Sep 9, 2017

We could run anser.ansiToText before copying it to the clipboard since we already have anser as an implicit dependency in our transforms.

pfackeldey pushed a commit to pfackeldey/hydrogen that referenced this pull request Sep 17, 2017
pfackeldey pushed a commit to pfackeldey/hydrogen that referenced this pull request Sep 17, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants