Skip to content

Commit

Permalink
docs: update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
AbaoFromCUG committed Apr 14, 2024
1 parent 1d5f09c commit e44d794
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 111 deletions.
69 changes: 69 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# Contributing

## JupyterLab Extension

### Development install

Note: You will need `NodeJS` to build the extension package. Recommend use `pnpm`

```bash
# Clone the repo to your local environment
# Change directory to the current project directory
# Install package in development mode
pip install -e "."
# Link your development version of the extension with JupyterLab
jupyter labextension develop . --overwrite
# Rebuild extension Typescript source after making changes
pnpm build
```

You can watch the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension's source and automatically rebuild the extension.

```bash
# Watch the source directory in one terminal, automatically rebuilding when needed
pnpm watch
# Run JupyterLab in another terminal
jupyter lab
```

With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt).

By default, the `pnpm build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command:

```bash
jupyter lab build --minimize=False
```

### Development uninstall

```bash
pip uninstall neopyter
```

In development mode, you will also need to remove the symlink created by `jupyter labextension develop`
command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions`
folder is located. Then you can remove the symlink named `neopyter` within that folder.

### Testing the extension

#### Frontend tests

This extension is using [Jest](https://jestjs.io/) for JavaScript code testing.

To execute them, execute:

```sh
pnpm install
pnpm test
```

#### Integration tests

This extension uses [Playwright](https://playwright.dev/docs/intro) for the integration tests (aka user level tests).
More precisely, the JupyterLab helper [Galata](https://github.com/jupyterlab/jupyterlab/tree/master/galata) is used to handle testing the extension in JupyterLab.

More information are provided within the [ui-tests](./ui-tests/README.md) README.

### Packaging the extension

See [RELEASE](RELEASE.md)
116 changes: 30 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,39 @@

## How does it work?

![](./doc/communication.png)
This project includes two parts: a [`JupyterLab extension`](https://jupyterlab.readthedocs.io/en/stable/user/extensions.html) and a Neovim plugin

The `Jupyter lab`'s frontend plugin provides RPC service which expose functions of `Jupyter lab`, Jupyterlab server
forward these RPC service by TCP Server. `Neovim`s plugin connect to TCP Server and call RPC service when receive events
from `Neovim` via `autocmd`. In the end, `Neopyter` can control `Juppyter lab`. `Neopyter` can implement more ability like [jupynium.nvim](https://github.com/kiyoon/jupynium.nvim), but better performance.
- The `JupyterLab extension` exposes functions of `Jupyter lab`, and provides a remote procedure call(RPC) service
- The `Neovim plugin` calls the RPC service when it receives events from `Neovim` via `autocmd`

| proxy | direct |
| :--------------------------------------------------------: | :----------------------------------------------------------: |
| <img alt="proxy mode" src="./doc/communication_proxy.png"> | <img alt="direct mode" src="./doc/communication_direct.png"> |

This project provides two working modes for different network environments. If the browser where your jupyiter lab is
located cannot directly access nvim, you must use `proxy` mode; If you need to collaborate and use the same Jupyter with
others, you must use direct mode

- `proxy` mode: Jupyterlab server
proxies the RPC service as a TCP server which `Neovim`s plugin connects to
- `direct` mode: Neovim plugin accesses these RPC service directly

Ultimately, `Neopyter` can control `Juppyter lab`. `Neopyter` can implement abilities like [jupynium.nvim](https://github.com/kiyoon/jupynium.nvim).

## Screenshots

| Completion | Cell Magic | Line Magic |
| :-----------------------------------------------: | :-----------------------------------------------: | :-----------------------------------------------: |
| <img alt="Completion" src="./doc/completion.png"> | <img alt="Cell Magic" src="./doc/cell_magic.png"> | <img alt="Line Magic" src="./doc/line_magic.png"> |

## Installation

### Requirements
## Requirements

- 📔JupyterLab >= 4.0.0
- ✌️ Neovim >= 9.0
- ✌️ Neovim nightly
- 👍`nvim-lua/plenary.nvim`
- 🤏`AbaoFromCUG/websocket.nvim` (optional for `rpc_client="websocket_server"`)
- 🤏`AbaoFromCUG/websocket.nvim` (optional for `mode="proxy"`)

## Installation

### JupyterLab Extension

Expand All @@ -34,11 +47,12 @@ To install the jupyterlab extension, execute:
pip install neopyter
```

To remove the extension, execute:
Configure `JupyterLab` in menu `Settings`>`Settings Editor`>`Neopyter`

```bash
pip uninstall neopyter
```
- `mode`: refer to the previous introduction about mode
- `IP`: if `mode=proxy`, set to the IP of the host where jupyter is located. If `proxy=direct`, set to the IP of the
host where neovim is located
- `port`: idle port

### Neovim plugin

Expand All @@ -50,9 +64,10 @@ With 💤lazy.nvim:
opts = {
-- auto define autocmd
auto_attach = true,
-- auto connect server
-- auto connect rpc service
auto_connect = true,
rpc_client = "async",
mode="direct",
-- same with JupyterLab settings
remote_address = "127.0.0.1:9001",
file_pattern = { "*.ju.*" },
on_attach = function(bufnr)
Expand Down Expand Up @@ -177,7 +192,6 @@ require'nvim-treesitter.configs'.setup {

- Open JupyterLab `jupyter lab`, there is a sidebar named `Neopyter`, which display neopyter ip+port
- Open a `*.ju.py` file in neovim
- [Optional] if `auto_attach` is `false`, you can connect jupyterlab manually via `:Neopyter connect 127.0.0.1:9001`
- Now you can type `# %%` in Neovim to create a code cell.
- You'll see everything you type below that will be synchronised in the browser

Expand Down Expand Up @@ -269,73 +283,3 @@ require'nvim-treesitter.configs'.setup {
## Acknowledges

- [jupynium.nvim](https://github.com/kiyoon/jupynium.nvim): Selenium-automated Jupyter Notebook that is synchronised with NeoVim in real-time.

## Contributing

### JupyterLab Extension

#### Development install

Note: You will need `NodeJS` to build the extension package. Recommend use `pnpm`

```bash
# Clone the repo to your local environment
# Change directory to the current project directory
# Install package in development mode
pip install -e "."
# Link your development version of the extension with JupyterLab
jupyter labextension develop . --overwrite
# Rebuild extension Typescript source after making changes
pnpm build
```

You can watch the source directory and run JupyterLab at the same time in different terminals to watch for changes in the extension's source and automatically rebuild the extension.

```bash
# Watch the source directory in one terminal, automatically rebuilding when needed
pnpm watch
# Run JupyterLab in another terminal
jupyter lab
```

With the watch command running, every saved change will immediately be built locally and available in your running JupyterLab. Refresh JupyterLab to load the change in your browser (you may need to wait several seconds for the extension to be rebuilt).

By default, the `pnpm build` command generates the source maps for this extension to make it easier to debug using the browser dev tools. To also generate source maps for the JupyterLab core extensions, you can run the following command:

```bash
jupyter lab build --minimize=False
```

#### Development uninstall

```bash
pip uninstall neopyter
```

In development mode, you will also need to remove the symlink created by `jupyter labextension develop`
command. To find its location, you can run `jupyter labextension list` to figure out where the `labextensions`
folder is located. Then you can remove the symlink named `neopyter` within that folder.

#### Testing the extension

##### Frontend tests

This extension is using [Jest](https://jestjs.io/) for JavaScript code testing.

To execute them, execute:

```sh
pnpm install
pnpm test
```

##### Integration tests

This extension uses [Playwright](https://playwright.dev/docs/intro) for the integration tests (aka user level tests).
More precisely, the JupyterLab helper [Galata](https://github.com/jupyterlab/jupyterlab/tree/master/galata) is used to handle testing the extension in JupyterLab.

More information are provided within the [ui-tests](./ui-tests/README.md) README.

#### Packaging the extension

See [RELEASE](RELEASE.md)
Binary file added doc/communication_direct.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
32 changes: 18 additions & 14 deletions doc/neopyter.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@ The bridge between Neovim and jupyter lab, edit in Neovim and preview/run in jup

------------------------------------------------------------------------------
*neopyter-usage*
neopyter.Option
Class ~
{neopyter.Option}
Fields ~
{remote_address} `(string)`
{file_pattern} `(string[])`
{auto_attach} `(boolean)` Automatically attach to the Neopyter server when open file_pattern matched files
{auto_connect} `(boolean)` # auto connect jupyter lab
{rpc_client}
"'async'" # AsyncRpcClient, default
"'block'" # BlockRpcClient
"'websocket_server'" # WSServerClient
{mode} "direct"|"proxy"
{filename_mapper} `(fun(ju_path:string):string)`
{on_attach} `(optional)` `(fun(bufnr:number))`
{jupyter} neopyter.JupyterOption
Expand All @@ -46,7 +44,7 @@ Fields ~
auto_attach = true,
auto_connect = true,
rpc_client = "async",
mode = "proxy",
jupyter = {
auto_activate_file = true,
-- Always scroll to the current cell.
Expand All @@ -69,7 +67,6 @@ Fields ~
},
}
<
Type ~
neopyter.Option
Expand All @@ -86,21 +83,24 @@ Parameters ~

==============================================================================
------------------------------------------------------------------------------
neopyter.JupyterOption
Class ~
{neopyter.JupyterOption}
Fields ~
{auto_activate_file} `(boolean)`

------------------------------------------------------------------------------
*JupyterLab*
`JupyterLab`
neopyter.JupyterLab
Class ~
{neopyter.JupyterLab}
Fields ~
{client} neopyter.RpcClient
{private} augroup `(number)`
{notebook_map} `({[string]:)` neopyter.Notebook}

------------------------------------------------------------------------------
neopyter.NewJupyterLabOption
Class ~
{neopyter.NewJupyterLabOption}
Fields ~
{address} `(optional)` `(string)`

Expand Down Expand Up @@ -167,7 +167,8 @@ Return ~
documents](https://jupyterlab.readthedocs.io/en/stable/user/commands.html#commands-list)

------------------------------------------------------------------------------
neopyter.NewUntitledOption
Class ~
{neopyter.NewUntitledOption}
Fields ~
{path} `(optional)` `(string)`
{type} `(optional)` `notebook`|`file`
Expand All @@ -185,7 +186,8 @@ current notebook of jupyter lab

==============================================================================
------------------------------------------------------------------------------
neopyter.Cell
Class ~
{neopyter.Cell}
Fields ~
{start_line} `(number)` include
{lines} `(string[])`
Expand All @@ -200,7 +202,8 @@ Fields ~
------------------------------------------------------------------------------
*Notebook*
`Notebook`
neopyter.Notebook
Class ~
{neopyter.Notebook}
Fields ~
{private} client neopyter.RpcClient
{bufnr} `(number)`
Expand All @@ -211,7 +214,8 @@ Fields ~
{private} augroup? `(number)`

------------------------------------------------------------------------------
neopyter.NewNotebokOption
Class ~
{neopyter.NewNotebokOption}
Fields ~
{client} neopyter.RpcClient
{bufnr} `(number)`
Expand Down
7 changes: 2 additions & 5 deletions lua/neopyter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,7 @@ local neopyter = {}
---@field file_pattern string[]
---@field auto_attach boolean Automatically attach to the Neopyter server when open file_pattern matched files
---@field auto_connect boolean # auto connect jupyter lab
---@field rpc_client
---| "'async'" # AsyncRpcClient, default
---| "'block'" # BlockRpcClient
---| "'websocket_server'" # WSServerClient
---@field mode "direct"|"proxy"
---@field filename_mapper fun(ju_path:string):string
---@field on_attach? fun(bufnr:number)
---@field jupyter neopyter.JupyterOption
Expand All @@ -47,7 +44,7 @@ neopyter.config = {

auto_attach = true,
auto_connect = true,
rpc_client = "async",
mode = "proxy",
jupyter = {
auto_activate_file = true,
-- Always scroll to the current cell.
Expand Down
1 change: 0 additions & 1 deletion lua/neopyter/health.lua
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ local function run_blocking(suspend_fn, ...)
local resolved = false
vim.schedule(function()
a.run(suspend_fn, function(ee)
print(ee)
resolved = true
end)
end)
Expand Down
11 changes: 8 additions & 3 deletions lua/neopyter/jupyter/jupyterlab.lua
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,14 @@ function JupyterLab:new(opts)

local config = require("neopyter").config
local RpcClient
if config.rpc_client == "block" then
RpcClient = require("neopyter.rpc.blockclient")
elseif config.rpc_client == "websocket_server" then
if config["rpc_client"] ~= nil then
vim.notify(
"`rpc_client` is deprecated, please reference to https://github.com/SUSTech-data/neopyter/issues/4",
vim.log.levels.ERROR,
{ title = "Neopyter" }
)
end
if config.mode == "direct" then
RpcClient = require("neopyter.rpc.wsserverclient")
else
RpcClient = require("neopyter.rpc.asyncclient")
Expand Down
4 changes: 2 additions & 2 deletions schema/labplugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,11 @@
"title": "Neopyter work mode",
"description": "Different work mode determine different methods of communication arcitecture. The `proxy` mode will communicate through jupyter server, while the `direct` mode will communicate directly with nvim",
"$ref": "#/definitions/mode",
"default": "proxy"
"default": "direct"
},
"ip": {
"title": "IP",
"description": "For `proxy` mode, this is the listening `IP:port` of the jupyter server's tcp server; for `direct` mode, this is `IP:port` of nvim's websocket server",
"description": "For `proxy` mode, this is the IP of the host where jupyter server is located; For `direct` mode, this is the IP of the host where nvim is located ",
"$ref": "#/definitions/ip",
"default": "127.0.0.1"
},
Expand Down

0 comments on commit e44d794

Please sign in to comment.