Skip to content

Commit

Permalink
Add support for the Go language (#1250)
Browse files Browse the repository at this point in the history
  • Loading branch information
mwouts committed Jul 9, 2024
1 parent 508f4ea commit ce74c51
Show file tree
Hide file tree
Showing 15 changed files with 786 additions and 1 deletion.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ Jupytext ChangeLog
- Some dependencies of the JupyterLab extensions were updated ([#1243](https://github.com/mwouts/jupytext/issues/1243), [#1245](https://github.com/mwouts/jupytext/issues/1245))

**Added**
- Added support for Lua notebooks ([#1252](https://github.com/mwouts/jupytext/pull/1252)) - thanks to [erentar](https://github.com/erentar) for this contribution
- Lua notebooks are now supported ([#1252](https://github.com/mwouts/jupytext/pull/1252)) - thanks to [erentar](https://github.com/erentar) for this contribution
- Go notebooks are supported too ([#1244](https://github.com/mwouts/jupytext/issues/1244))! Many thanks to [Jan Pfeifer](https://github.com/janpfeifer), author of [GoNB](https://github.com/janpfeifer/gonb), and to [HaveF](https://github.com/HaveF) for their help on this topic.
- Empty prefixes are now allowed in Jupytext format when specified as a dictionary ([#1144](https://github.com/mwouts/jupytext/issues/1144))


Expand Down
1 change: 1 addition & 0 deletions docs/languages.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Jupytext works with notebooks in any of the following languages:
- Coconut
- F#
- Gnuplot
- Go
- Groovy
- Haskell
- IDL
Expand Down
5 changes: 5 additions & 0 deletions src/jupytext/cell_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,11 @@ def uncomment_code_and_magics(self, lines):
else:
lines = uncomment(lines)

if self.default_language == "go" and self.language is None:
lines = [
re.sub(r"^((//\s*)*)(//\s*gonb:%%)", r"\1%%", line) for line in lines
]

if self.cell_type == "code":
return unescape_code_start(
lines, self.ext, self.language or self.default_language
Expand Down
14 changes: 14 additions & 0 deletions src/jupytext/cell_to_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,13 @@ def cell_to_text(self):
if self.cell_type != "code" and not self.metadata and self.use_triple_quotes():
self.metadata["cell_type"] = self.cell_type

# Go notebooks have '%%' or '%% -' magic commands that need to be escaped
if self.default_language == "go" and self.language == "go":
self.source = [
re.sub(r"^(//\s*)*(%%\s*$|%%\s+-.*$)", r"\1//gonb:\2", line)
for line in self.source
]

if self.is_code():
return self.code_to_text()

Expand Down Expand Up @@ -487,6 +494,13 @@ def __init__(self, *args, **kwargs):

def cell_to_text(self):
"""Return the text representation for the cell"""
# Go notebooks have '%%' or '%% -' magic commands that need to be escaped
if self.default_language == "go" and self.language == "go":
self.source = [
re.sub(r"^(//\s*)*(%%\s*$|%%\s+-.*$)", r"\1//gonb:\2", line)
for line in self.source
]

active = is_active(
self.ext, self.metadata, same_language(self.language, self.default_language)
)
Expand Down
5 changes: 5 additions & 0 deletions src/jupytext/languages.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Determine notebook or cell language"""
import re

# Jupyter magic commands that are also languages
_JUPYTER_LANGUAGES = [
Expand Down Expand Up @@ -92,6 +93,7 @@
},
".xsh": {"language": "xonsh", "comment": "#"},
".lua": {"language": "lua", "comment": "--"},
".go": {"language": "go", "comment": "//"},
}

_COMMENT_CHARS = [
Expand All @@ -110,6 +112,7 @@
_JUPYTER_LANGUAGES_LOWER_AND_UPPER = _JUPYTER_LANGUAGES.union(
{str.upper(lang) for lang in _JUPYTER_LANGUAGES}
)
_GO_DOUBLE_PERCENT_COMMAND = re.compile(r"^(%%\s*|%%\s+-.*)$")


def default_language_from_metadata_and_ext(metadata, ext, pop_main_language=False):
Expand Down Expand Up @@ -206,6 +209,8 @@ def cell_language(source, default_language, custom_cell_magics):
"""Return cell language and language options, if any"""
if source:
line = source[0]
if default_language == "go" and _GO_DOUBLE_PERCENT_COMMAND.match(line):
return None, None
if default_language == "csharp":
if line.startswith("#!"):
lang = line[2:].strip()
Expand Down
4 changes: 4 additions & 0 deletions src/jupytext/magics.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ def get_comment(ext):
_MAGIC_FORCE_ESC_RE["csharp"] = re.compile(r"^(// |//)*#![a-zA-Z](.*)//\s*escape")
_MAGIC_FORCE_ESC_RE["csharp"] = re.compile(r"^(// |//)*#![a-zA-Z](.*)//\s*noescape")

# Go magics might start with % or ! or !*
# (in addition, Go NB might use %% or %% -, see "_GO_DOUBLE_PERCENT_COMMAND")
_MAGIC_RE["go"] = re.compile(r"^(// |//)*(!|!\*|%|%%|%%%)[a-zA-Z]")

# Commands starting with a question or exclamation mark have to be escaped
_PYTHON_HELP_OR_BASH_CMD = re.compile(r"^\s*(# |#)*\s*(\?|!)\s*[A-Za-z\.\~\$\\\/\{\}]")

Expand Down
149 changes: 149 additions & 0 deletions tests/data/notebooks/inputs/ipynb_go/hello_world_gonb.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "8795db3a-af9a-4f03-a68d-019330861b54",
"metadata": {},
"source": [
"A notebook that use [GoNB](https://github.com/janpfeifer/gonb)"
]
},
{
"cell_type": "markdown",
"id": "50a2fb21-01b3-46d0-9951-f9a1301a85ca",
"metadata": {},
"source": [
"the code below comes from [tutorial.ipynb](https://github.com/janpfeifer/gonb/blob/main/examples/tutorial.ipynb)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "75d8418d-a918-4cc8-b42e-384db01f21ae",
"metadata": {},
"outputs": [],
"source": [
"func main() {\n",
" fmt.Printf(\"Hello World!\")\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3620f46f-efd5-4454-bc29-418297012ce9",
"metadata": {},
"outputs": [],
"source": [
"%%\n",
"fmt.Printf(\"Hello World!\")"
]
},
{
"cell_type": "markdown",
"id": "7fed4a43",
"metadata": {},
"source": [
"%% --who=world can pass flags to main func"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "473e2d02",
"metadata": {},
"outputs": [],
"source": [
"import (\n",
" \"flag\"\n",
" \"fmt\"\n",
")\n",
"\n",
"var flagWho = flag.String(\"who\", \"\", \"Your name!\")\n",
"\n",
"%% --who=world\n",
"fmt.Printf(\"Hello %s!\\n\", *flagWho)"
]
},
{
"cell_type": "markdown",
"id": "b8e8b4ae",
"metadata": {},
"source": [
"%args also can pass flags"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "348efbe1",
"metadata": {},
"outputs": [],
"source": [
"%args --who=Wally\n",
"\n",
"func main() {\n",
" flag.Parse()\n",
" fmt.Printf(\"Where is %s?\", *flagWho)\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "82f4bb1f-3311-4fca-8025-c54c0305dc64",
"metadata": {},
"outputs": [],
"source": [
"import \"github.com/janpfeifer/gonb/gonbui\"\n",
"\n",
"%%\n",
"gonbui.DisplayHtml(`<span style=\"background:pink; color:#111; border-radius: 3px; border: 3px solid orange; font-size: 18px;\">I 🧡 GoNB!</span>`)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "1a5584ff-f346-45cf-95c1-a3e3b7146c6c",
"metadata": {},
"outputs": [],
"source": [
"%%\n",
"gonbui.DisplayMarkdown(\"#### Objective\\n\\n1. Have fun coding **Go**;\\n1. Profit...\\n\"+\n",
" `$$f(x) = \\int_{-\\infty}^{\\infty} e^{-x^2} dx$$`)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "de996381-d92c-4ce6-a135-50cf39288aa1",
"metadata": {},
"outputs": [],
"source": [
"func init_a() {\n",
" fmt.Println(\"init_a\")\n",
"}\n",
"%%\n",
"fmt.Println(\"main\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Go (gonb)",
"language": "go",
"name": "gonb"
},
"language_info": {
"codemirror_mode": "",
"file_extension": ".go",
"mimetype": "",
"name": "go",
"nbconvert_exporter": "",
"pygments_lexer": "",
"version": "go1.21.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
69 changes: 69 additions & 0 deletions tests/data/notebooks/outputs/ipynb_to_Rmd/hello_world_gonb.Rmd
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
---
jupyter:
kernelspec:
display_name: Go (gonb)
language: go
name: gonb
---

A notebook that use [GoNB](https://github.com/janpfeifer/gonb)


the code below comes from [tutorial.ipynb](https://github.com/janpfeifer/gonb/blob/main/examples/tutorial.ipynb)

```{go}
func main() {
fmt.Printf("Hello World!")
}
```

```{go}
%%
fmt.Printf("Hello World!")
```

%% --who=world can pass flags to main func

```{go}
import (
"flag"
"fmt"
)
var flagWho = flag.String("who", "", "Your name!")
%% --who=world
fmt.Printf("Hello %s!\n", *flagWho)
```

%args also can pass flags

```{go}
// %args --who=Wally
func main() {
flag.Parse()
fmt.Printf("Where is %s?", *flagWho)
}
```

```{go}
import "github.com/janpfeifer/gonb/gonbui"
%%
gonbui.DisplayHtml(`<span style="background:pink; color:#111; border-radius: 3px; border: 3px solid orange; font-size: 18px;">I 🧡 GoNB!</span>`)
```

```{go}
%%
gonbui.DisplayMarkdown("#### Objective\n\n1. Have fun coding **Go**;\n1. Profit...\n"+
`$$f(x) = \int_{-\infty}^{\infty} e^{-x^2} dx$$`)
```

```{go}
func init_a() {
fmt.Println("init_a")
}
%%
fmt.Println("main")
```
66 changes: 66 additions & 0 deletions tests/data/notebooks/outputs/ipynb_to_hydrogen/hello_world_gonb.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// -*- coding: utf-8 -*-
// ---
// jupyter:
// kernelspec:
// display_name: Go (gonb)
// language: go
// name: gonb
// ---

// %% [markdown]
// A notebook that use [GoNB](https://github.com/janpfeifer/gonb)

// %% [markdown]
// the code below comes from [tutorial.ipynb](https://github.com/janpfeifer/gonb/blob/main/examples/tutorial.ipynb)

// %%
func main() {
fmt.Printf("Hello World!")
}

// %%
//gonb:%%
fmt.Printf("Hello World!")

// %% [markdown]
// //gonb:%% --who=world can pass flags to main func

// %%
import (
"flag"
"fmt"
)

var flagWho = flag.String("who", "", "Your name!")

//gonb:%% --who=world
fmt.Printf("Hello %s!\n", *flagWho)

// %% [markdown]
// %args also can pass flags

// %%
%args --who=Wally

func main() {
flag.Parse()
fmt.Printf("Where is %s?", *flagWho)
}

// %%
import "github.com/janpfeifer/gonb/gonbui"

//gonb:%%
gonbui.DisplayHtml(`<span style="background:pink; color:#111; border-radius: 3px; border: 3px solid orange; font-size: 18px;">I 🧡 GoNB!</span>`)

// %%
//gonb:%%
gonbui.DisplayMarkdown("#### Objective\n\n1. Have fun coding **Go**;\n1. Profit...\n"+
`$$f(x) = \int_{-\infty}^{\infty} e^{-x^2} dx$$`)

// %%
func init_a() {
fmt.Println("init_a")
}
//gonb:%%
fmt.Println("main")
Loading

0 comments on commit ce74c51

Please sign in to comment.