webpage icon indicating copy to clipboard operation
webpage copied to clipboard

Allow for code blocks to run on the playground

Open gnikit opened this issue 3 years ago • 16 comments

It would be great if we could allow via a button for the examples that we provide in the Quickstart Tutorial to run in the playground. I noticed the examples fall in 3 different categories:

  1. Working examples, would compile and run as-is, no modification necessary.
  2. Examples that need to be surrounded with program main/end program main or some other type of boilerplate code.
  3. Examples that need to be appended together to make a Working Example e.g. https://fortran-lang.org/en/learn/quickstart/variables/#standard-input-output

Not every code block needs to be able to run in the playground but it would be cool if we could get users from reading to coding as quickly as possible.

gnikit avatar Sep 22 '22 11:09 gnikit

I don't think this is possible in CSS or MyST-Markdown, but requires a custom sphinx extension. To make this practical we need a way to extract the code block from the docutils node, render it as code block and insert a link to run it on the playground (maybe in a header or like the copy button).

awvwgk avatar Sep 22 '22 12:09 awvwgk

This is a very good Example of it. https://zmoon.github.io/FortranTipBrowser/tips/006.html , currently using godbolt.

henilp105 avatar Sep 22 '22 12:09 henilp105

@gnikit as also suggested by @awvwgk we would need a to extract all the codeblocks , then we would need a API ( to accept code in our format which is different from their current implementation) from playground to run code.

henilp105 avatar Sep 22 '22 12:09 henilp105

@awvwgk The solution I was thinking was using Python. We would add some comment markers before the code blocks e.g.

<!--
"pg_use" : true,
"pg_pre" : "program main\n  implicit none\n",
"pg_post" : "end program main\n"
-->
```fortran
integer :: i
i = 10
print *, i
```

Here I used JSON since it's trivial to parse. Combine the above code with the codeblock and then communicate that with the playground (somehow). However, I don't know if the playground offers any API

gnikit avatar Sep 22 '22 12:09 gnikit

Basically, I think the extraction of the codeblocks is the easy part and there are plenty of solutions for that. Communicating the with the playground will probably be the hard bit here.

gnikit avatar Sep 22 '22 12:09 gnikit

@gnikit playground has its primary API to communicate with the compiler, ( its hosted at play-api.fortran-lang.org) , Just we would have to format our code to make it work with our implementation.

henilp105 avatar Sep 22 '22 12:09 henilp105

Just we would have to format our code to make it work with our implementation.

Can you explain a bit what you mean by that?

gnikit avatar Sep 22 '22 13:09 gnikit

current playground API uses the following format ( {"code":"program hello\r\n ! This is a comment line; it is ignored by the compiler\r\n print *, 'Hello, World!'\r\nend program hello\r\n","programInput":"","libs":[]} ) , as you can see here the fortran code is slightly formatted with '\r' or '\n' and some other keywords by ace mostly, so we would have to change our existing code before sending via API.

henilp105 avatar Sep 22 '22 13:09 henilp105

Thanks for the explanation. I don't see why we would have to change our docs. If we use a Python scripts, that extracts, packages and then sends the API request when pressing a button, the work for doing any post-processing on the code would fall on the Python script not the codeblock itself.

Anyway, I am not convinced that the carriage return character is even necessary for the API to work especially since the playground runs on a Linux server

gnikit avatar Sep 22 '22 13:09 gnikit

yes sir , but one of the things to consider would also be how to recieve the response of request via API , for that we would have to make playground just receive code and then the user could run it via the playground. They have opened an Issue for the same ( Please refer # 51 https://github.com/fortran-lang/playground/issues/51 ) .

henilp105 avatar Sep 22 '22 13:09 henilp105

@gnikit sir, I have added an API for the same , please refer Readme of the playground for integration information, would also open a PR for extracting code from docs.

Thanks and Regards, Henil

henilp105 avatar Sep 25 '22 17:09 henilp105

The issue should be closed when the integration to the website is done. Is there an existing pr or a commit doing that? If not how else is this going to be tracked if we close the issue?

gnikit avatar Sep 25 '22 17:09 gnikit

Sure sir.

henilp105 avatar Sep 25 '22 17:09 henilp105

I found this https://github.com/earldouglas/codedown very helpfull for extracting the codeblocks, or we could also use regex ``{3}([\w]*)\n([\S\s]+?)\n{3} for extracting code blocks which should be the most apt way to extract them ?@awvwgk @gnikit

henilp105 avatar Sep 27 '22 17:09 henilp105

Here is a minimal patch for creating a custom code-block directive

diff --git a/ext/fortran_playground.py b/ext/fortran_playground.py
new file mode 100644
index 000000000..a6a3e34dc
--- /dev/null
+++ b/ext/fortran_playground.py
@@ -0,0 +1,18 @@
+from sphinx.directives.code import CodeBlock
+from docutils import nodes
+
+class PlayCodeBlock(CodeBlock):
+
+    def run(self):
+        text = '\n'.join(self.content)
+        return [*super().run(), nodes.literal_block(text, text)]
+
+
+def setup(app):
+    app.add_directive('play-code-block', PlayCodeBlock)
+
+    return {
+        'version': '0.1',
+        'parallel_read_safe': True,
+        'parallel_write_safe': True,
+    }
diff --git a/source/conf.py b/source/conf.py
index 60a06560b..5b38525ad 100644
--- a/source/conf.py
+++ b/source/conf.py
@@ -25,6 +25,8 @@ import pathlib
 
 root = pathlib.Path(__file__).parent.parent
 
+sys.path.insert(0, str(root / "ext"))
+
 data_files = {
     "fortran-learn": pathlib.Path(root, "_data", "fortran_learn.json"),
     "fortran-packages": pathlib.Path(root, "_data", "fortran_package.json"),
@@ -68,6 +70,7 @@ extensions = [
     "sphinx_copybutton",
     "sphinx.ext.intersphinx",
     "sphinx_jinja",
+    "fortran_playground",
 ]
 
 myst_enable_extensions = [
diff --git a/source/learn/quickstart/hello_world.md b/source/learn/quickstart/hello_world.md
index a5d891a1a..cdf652c94 100644
--- a/source/learn/quickstart/hello_world.md
+++ b/source/learn/quickstart/hello_world.md
@@ -39,7 +39,7 @@ warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
 Once you have set up your compiler, open a new file in your favourite code editor and enter the following:
 
-```fortran
+```{play-code-block} fortran
 program hello
   ! This is a comment line; it is ignored by the compiler
   print *, 'Hello, World!'

All it does is showing the original code-block output and adding the verbatim code-block without highlighting afterward. We would turn this into a link to the playground after encoding its content.

awvwgk avatar Sep 27 '22 18:09 awvwgk

@awvwgk @gnikit Thanks for the apt code inspiration, I have implemented links for all sections Except Intrinsics . Would like to request review Implementation. in #184

henilp105 avatar Oct 07 '22 14:10 henilp105