live-codes / livecodes

Code Playground That Just Works!
https://livecodes.io
MIT License
778 stars 66 forks source link

Feature: Add the ability to pass stdin through the config object in Headless mode #472

Closed jaytecch closed 10 months ago

jaytecch commented 10 months ago

Type of feature

✨ Feature

Current behavior

No response

Suggested feature

It would be nice to be able to pass the stdin for languages like python through the config object rather than always using the window prompt. This should also be available in headless mode.

Currently, running a python script that requires an input throws an error in the console when in an headless mode, saying a call to prompt() was ignored due to allow-modals not being set to true.

Screenshot 2023-11-11 041848

Additional context

No response

Code of Conduct

Contributing Docs

hatemhosny commented 10 months ago

Thank you @jaytecch

Please share a snippet of your code, or even better share a project (app menu -> share), so that I can get an idea about what you are trying to achieve.

hatemhosny commented 10 months ago

I assume you want to use input in your Python code and want to provide the value it returns without showing the browser prompt. something like this:

name = input("What is your name?")
print("Hello, " + name)

age = input("How old are you?")
print("You are " + age + " years old")

you can override window.prompt in a script added to the markup editor. e.g.

<script>
  window.prompt = (q) => {
    if (q === 'What is your name?') {
     return 'John';
    }
    if (q === 'How old are you?') {
     return '20';
    }
  }
</script>

demo: https://livecodes.io/?x=id/mqgkf99bfn9&console=open

is that what you are trying to achieve?

jaytecch commented 10 months ago

Hi, thanks for your quick response. Yes, what I want is a way to pass the "input" in my python code a value without having to use the window prompt. I suppose there could be a field in the config object that could make this easier. However, I will implement the solution that you have provided, thanks. I just thought being able to pass it with other configurations will be cleaner.

hatemhosny commented 10 months ago

I know it does not feel right to override globals, however in your specific use case this might be the best option.

Passing a value in the config object will have to be static (functions are not allowed in config object). So you cannot respond to different questions by different values. In addition, this will not be consistent across different languages.

Since you are using headless mode, so just adding the override code to markup editor might be ok. However, if you want to embed a regular playground, you may not want to show this code to users. The config object properties for editors (markup, style, script and tests) allow you to pass a hiddenContent property, for code that runs without being visible in the code editor (see docs).

example:

import { createPlayground } from 'livecodes';

createPlayground('#container', {
  config: {
    markup: {
      language: 'html',
      content: `<p>code visible in code editor</p>`,
      hiddenContent: `<p>hidden code that still works!</p>`,
    }
  }
});

so for your case, you may want to override the input function in Python, like this:

import { createPlayground } from 'livecodes';

createPlayground('#container', {
  config: {
    languages: ['python'],
    script: {
      language: 'python',
      content: `
name = input("What is your name?")
print("Hello, " + name)

age = input("How old are you?")
print("You are " + age + " years old")
`.trimStart(),
    hiddenContent: `
def input(q):
  if q == "What is your name?":
    return "John"
  elif q == "How old are you?":
    return "20"
  else:
    return ""    
`.trimStart(),
    },
    tools: {
      status: 'open',
    },
  }
});

demo: https://livecodes.io/?x=id/83enj8j8f3p

hatemhosny commented 10 months ago

Please note that some languages do allow passing a value to stdin like in C++ by setting the property livecodes.cpp.input.

Example: https://livecodes.io/?template=cpp&activeEditor=markup

jaytecch commented 10 months ago

@hatemhosny , thanks a lot for the help and quick responses. I have one more request for now, don't know if it's already available currently. I have been working on a bubble io plugin that allows users to easily create their own codepen clone in minutes. With this project, you've really helped me simplify a lot of things. I will only be utilizing the "result" display mode in the plugin as users will be able to use any editor of their choice, my plugin makes an Ace editor available by default. In regard to this, is there a way to optionally remove the small overlay of the logo which shows on hover. Or the logo could just show on hover(so people can know the preview is made available by livecodes) but not be a link.

hatemhosny commented 10 months ago

@jaytecch In result mode, the whole playground UI is hidden, and only the result page is visible.

This URL will be on LiveCodes domain, so if this is shared, people may think this is an official page by LiveCodes (like docs, ...etc).

example: https://livecodes.io/?x=id/di3ryxaxcug&mode=result

So I added the hover with the link to make sure people know that this is a project created on LiveCodes not an official page.

However, if you need to get the result page, you may use the SDK method: getCode. You can get the result HTML and then you can show it in an iframe yourself.

import { createPlayground } from 'livecodes';

createPlayground('#container').then(async (playground) => {
  const code = await playground.getCode();
  // result page HTML
  const result = code.result;

  // use it like this or any other way (watch for security concerns)
  const iframe = document.createElement("iframe");
  iframe.srcdoc = result;
  document.body.appendChild(iframe);
});
jaytecch commented 10 months ago

@hatemhosny , thanks a bunch. I will now close this issue

hatemhosny commented 10 months ago

@jaytecch you are most welcome!

please let me know if you build something on top of LiveCodes. I may also share it. best wishes